Monday, 4 May 2015

Traps of adding terms - wp set post terms

Usage of wp_set_post_terms

 <?php wp_set_post_terms( $post_id, $terms, $taxonomy, $append ) ?>
The usage is clearly demonstrated on codex.wordpress.org, but there are a couple of traps for the parameters of $tems and $append

How to add multiple terms for a specific post

There are two ways to do it. The first one is by setting $append true and passing a single term to the parameter of $terms, but the value of $append is set false by default. The alternative method is passing all the terms as a string or an array to the parameter of $terms and using the default value of $append.

The type of the parameter of $terms matters

When add a single term to a post, no matter the type is int or string it will work. Here is an example.
        $locationTerm = 'auckland';
        $locationTaxonomy = 'dealer-location';
        $termId = term_exists($locationTerm, $locationTaxonomy);//term_exists returns an array that contains values of string
        if(!$termId){
            $termId = wp_insert_term( $locationTerm, $locationTaxonomy);
        }
        $termId = $termId['term_id']; //the type of $termId is string
        return wp_set_post_terms( $post->ID, $termId, $locationTaxonomy);

However, the similar code doesn't work for adding multiple terms. Here is an example which doesn't work.
        $featureTerms = 'ABS, 4 Airbags';
        $featureTaxonomy = 'car-feature';
        $arrFeatureTerms = explode(',', $featureTerms);
        $arrTermIds = array();
        foreach ($arrFeatureTerms as $featureTerm){
            $featureTerm = trim($featureTerm);
            if(!empty($featureTerm)){
                $termId = term_exists($featureTerm, $featureTaxonomy);
                if(!$termId){
                    $termId = wp_insert_term( $featureTerm, $featureTaxonomy);
                }
                $termId = $termId['term_id'];
                $arrTermIds[] = $termId;
            }
        }
        wp_set_post_terms( $post->ID, $arrTermIds, $featureTaxonomy);

Since the type of $termId = $termId['term_id']; is string, WP will consider $termId as a term rather than an Id of the term. As a result, WP will create a new term using the value of $termId and attach the newly created integer term to the post which is against our expectation.

To make WP work as we expected, what we need to do is to convert the $termId to int type as below:
        $termId = (int)$termId['term_id'];
The full snippet should be like the following:
        $featureTerms = 'ABS, 4 Airbags';
        $featureTaxonomy = 'car-feature';
        $arrFeatureTerms = explode(',', $featureTerms);
        $arrTermIds = array();
        foreach ($arrFeatureTerms as $featureTerm){
            $featureTerm = trim($featureTerm);
            if(!empty($featureTerm)){
                $termId = term_exists($featureTerm, $featureTaxonomy);
                if(!$termId){
                    $termId = wp_insert_term( $featureTerm, $featureTaxonomy);
                }
                $termId = (int)$termId['term_id'];
                $arrTermIds[] = $termId;
            }
        }
        wp_set_post_terms( $post->ID, $arrTermIds, $featureTaxonomy);

A slight change make it work, but it might take a long time to figure it out.