post: WordPress: Term_Exists and Parent_ID. Correct Usage and Unintended Consequences.


WordPress: Term_Exists and Parent ID

Working With WordPress



Taxonomy WordPress

I recently had an issue with a popular WordPress plugin when importing taxonomies into a custom post type. The plugin carried out a test to check if the taxonomy already exists. If so, then the post was attached to the existing term, if not then a new top level term was created and the post attached to that.

The existing taxonomy structure to be imported into was a standard 3-level hierarchy of parent > child > sub-child with a dozen or so parent categories and several hundred child and sub-child elements.

All well and good? Well, no. The problem was that existing terms were not being found and instead duplicate top level taxonomies were being created with xxx-2 slugs and posts attached to these new terms, essentially corrupting the hierarchy. On investigation it was appearing that only top level taxonomy terms were being found, not descendants.

On looking at the code it appeared that the check for whether a term existed for the particular taxonomy was implicitly being passed an integer 0 as the third parent_id parameter. This restricts the search to top-level terms only, and returns ’empty’ if the term is not found.

<?php term_exists( $term, $tax, 0 ); ?>

I’m not sure if this was an intentional feature, or simply an error in usage of the parameter and function.

The problem is that what the codex says and what the code says is different and may lead to inadvertent confusion and potential bugs – or unrequested features.

In the codex:

Check if a given term exists and return the term ID, a term array, or 0 (false) if the term doesn't exist. 

$term (integer|string) (required) The term to check Default: None 
$taxonomy (string) (optional) The taxonomy name to use Default: '' 
$parent (integer) (optional) $parent ID of parent term under which to confine the exists search Default: 0 

Return Values (mixed) 
Returns 0 or NULL if the term does not exist. 
Returns the term ID if no taxonomy was specified and the term exists. 
Returns an array if the pairing exists. (format: array('term_id'=>term id, 'term_taxonomy_id'=>taxonomy id)) 

In the code: wp-includes/taxonomy.php

 * Check if Term exists.
 * Formerly is_term(), introduced in 2.3.0.
 * @since 3.0.0
 * @global wpdb $wpdb WordPress database abstraction object.
 * @param int|string $term The term to check
 * @param string $taxonomy The taxonomy name to use
 * @param int $parent Optional. ID of parent term under which to confine the exists search.
 * @return mixed Returns null if the term does not exist. Returns the term ID
 *               if no taxonomy is specified and the term ID exists. Returns
 *               an array of the term ID and the term taxonomy ID the taxonomy
 *               is specified and the pairing exists.
function term_exists( $term, $taxonomy = '', $parent = null ) {

You can clearly see the problem. The codex is wrong. It states that the default for the parent_id parameter is 0. The code says that it is null. The significance of this is that the code checks if the parameter is an integer before deciding if it is to be added to the sql.

So there is it, be very certain what you are testing for when using term_exists or you may have unintended consequences.

  • – If you are searching for a child of a top-level category then pass 0 as the parent_id 3rd parameter to the 2nd parameter taxonomy.
  • – If you don’t know if the term has a parent, or children, or don’t care then leave the parent_id parameter out.
  • – If you want to check against a particular parent_id and know what it is, then pass that as the 3rd parameter.

All other checks are incorrect usage of term_exists.

comments powered by Disqus