Quantcast
Viewing all articles
Browse latest Browse all 10

Don’t Share Terms Between WordPress Taxonomies

Image may be NSFW.
Clik here to view.
By default WordPress will reuse terms with the same name and slug between different taxonomies. For instance, if you add the term ‘red’ as a tag, and then add the category ‘red’, the same wp_terms record will be shared between them. This is also true for any custom taxonomies you define (remember that despite their seeming differences, WordPress tags and categories are both implemented as taxonomies). Now, in general this is fine; if the name and slug are the same, then just given the fact that all term records are stored in a single table forces them to be shared across different taxonomies.

However, what if you don’t care so much about the slug, and want to be able to use the same term name within multiple taxonomies, but don’t want the wp_terms record shared? I’ll admit this might not be a typical case, but it came up for me recently when doing some WooCommerce work, specifically because I wanted to be able to attach different term meta to each of the terms with the same name, so they couldn’t be shared between taxonomies. (Side note: WooCommerce allows you to attach meta information to term records, a really cool extension to WordPress with lots of uses, and I plan to cover that implementation in a future article.) One simple way to stop the records from being shared is to make the admin user define a unique slug for each term that shares a common name with another taxonomical term, ie: ‘Red’, ‘red’ in taxonomy ‘A’ and ‘Red’, ‘red-2′ in taxonomy ‘B’, etc. Obviously the drawback is that you have to remember to do this, have to remember how many different ‘red’ terms there are, all easy stuff to forget until it’s too late. So, as usual I’ve put together a little modification that you can add to your theme’s functions.php, or to your very own custom site plugin and explained below.

The Code

The implementation is actually fairly simple: we hook a filter to ‘pre_insert_term’ and temporarily rename the term as needed to generate a unique slug and thus a separate term record, then after the term is created we fix the name back to what the user originally specified. This is done only if a term slug is not given; we assume the user had something special in mind if they went through the trouble of providing a slug. And with that, here’s the code:

add_filter( 'pre_insert_term', 'foxrunsoftware_pre_insert_term', 10, 2 );

/**
 * This filter temporarily renames any terms to force a unique slug when they
 * would otherwise not be unique.  This is to overcome a "feature" with 
 * WordPress, whereby terms are recycled among different taxonomies rather than 
 * being created new with a unique slug.  As an example, if the term 'red' 
 * exists in a taxonomy and 'red' is added to another taxonomy, it will be 
 * temporarily named as 'red 2', which forces a unique slug to be created, then
 * we remove the name counter suffix after the term is created.
 * 
 * @param string $term the term name
 * @param string $taxonomy the taxonomy name
 * 
 * @return string the term name
 */
function foxrunsoftware_pre_insert_term( $term, $taxonomy ) {
  
  // if no slug was specified
  if ( empty( $_REQUEST['slug'] ) ) {
    $slug = sanitize_title( $term );
    
    // check whether a unique slug needs to be generated
    $new_slug = wp_unique_term_slug( $slug, (object) array( 'parent' => 0, 'taxonomy' => $taxonomy ) );
    
    if ( $new_slug != $slug ) {
      // append the unique slug counter to the end of the term name, to force uniqueness
      $term .= ' ' . substr( $new_slug, strrpos( $new_slug, '-' ) + 1 );
      
      // hook so we can fix the term name back to what it should be
      add_action( 'created_term', 'foxrunsoftware_created_term', 10, 3 );
    }
  }
  
  return $term;
}

As you can see, after changing the term name if needed, a second action is added to fix the modified term name. The implementation of that function is as follows:

/**
 * This action removes the temporary counter which is added to terms to force 
 * uniqueness.
 * 
 * See the commends for the foxrunsoftware_pre_insert_term() function
 * for the full details.  
 * 
 * @see foxrunsoftware_pre_insert_term()
 * 
 * @param int $term_id term identifier
 * @param int $tt_id term taxonomy identifier
 * @param string $taxonomy taxonomy name
 */
function foxrunsoftware_created_term( $term_id, $tt_id, $taxonomy ) {
  
  $term = get_term( $term_id, $taxonomy );
  
  // get rid of the temporary counter we added to the name
  $name = substr( $term->name, 0, strrpos( $term->name, ' ' ) );
  
  // update and we're done!
  wp_update_term( $term_id, $taxonomy, array( 'name' => $name ) );
}

And that’s the whole of it. If there’s anyone else out there who did not want their terms shared between taxonomies, let me know in the comments below, I’d be curious to hear what you’re doing!

The post Don’t Share Terms Between WordPress Taxonomies appeared first on Fox Run Software.


Viewing all articles
Browse latest Browse all 10

Trending Articles