Update taxonomy value of post type in query

I have a situation where i have about 5000 imported records in a custom post type (travel) with a taxonomy category (country). Since i import from several different locations and each source seems to use a different description for some countries i want to update the term reference of that post to a uniform description.

So say the taxonomy ‘country’ has, amongst others, these values:


+---------+-------------+
| term_id | name        |
+---------+-------------+
|  1248   | Zuid Afrika |
+---------+-------------+
|  3845   | zuid-afrika |
+---------+-------------+

I want to update the term reference to ‘country’ that has a duplicate in each ‘travel’ post to a new defined id.


$terms = array(
    '3845' => '1248'
);
$args = array(
    'posts_per_page'    => -1,
    'post_type'         => 'travel',
    'post_status'       => 'publish'
);
global $post;
$my_query = new WP_Query($args);
if($my_query->have_posts()){
    while ($my_query->have_posts()) : $my_query->the_post();
        /*
            This is the part where i get lost, what i want is something like this, but this doesn't work
        */
        if(in_array($post->term_id,$terms){
            update term reference with value $terms[$post->term_id];
        }
    }
    endwhile;
    wp_reset_query();
}

Any help would be really appreciated because i’m pretty much stuck right now

Edit:
I don’t want to delete the taxonomy categories because this scripts will run after the imports so if the duplicates are deleted they will be imported straight back but with a different term id

3 Answers
3

There are quite a few steps involved here and also, with that 5000 posts figure you are mentioning, this will be an expensive task to do it through WordPress itself. However, here is what I came up with (I haven’t tested this so you may wish to use it on a backup first and see if it works):

global $wpdb;

/* The ( 'from_term_id', 'to_term_id' ) map. */
$terms_map = array(
    '3845' => '1248',
    /* ... The rest of your mapping */
);

$taxonomy = 'country';
$obj_terms = wp_get_object_terms( $post->ID, $taxonomy );

/* Loop through each object term */
foreach ( $obj_terms as $term ) {
    /* See if the obj term_id is a key in $terms_map */
    if ( isset( $terms_map[$term->term_id] ) ) {
        /* We have a valid key. We now need the term_taxonomy_ids */
        /* for both 'from_term_id' and 'to_term_id' */
        $to_term = get_term( $terms_map[$term->term_id], $taxonomy );

        $from_term_tax_id = $term->term_taxonomy_id;
        $to_term_tax_id = $to_term->term_taxonomy_id;

        /* Update the '{prefix}_term_relationships' table */
        $update_res = $wpdb->update( 
            $wpdb->term_relationships, /* The table to update */
            array( 'term_taxonomy_id' => $to_term_tax_id ), /* Data to be updated */
            array( 'object_id' => $post->ID, 'term_taxonomy_id' => $from_term_tax_id ), /* Where clause */
            array( '%d' ), /* Format of the data is int */
            array( '%d', '%d' ) /* Format of the where clause is int */
        );

        /* Finally, you may wish to update the term count for each term */
        wp_update_term_count( array( $from_term_tax_id, $to_term_tax_id ), $taxonomy );
    }
}

Like I’ve mentioned though this may prove to be too expensive in which case you will have to write a separate PHP script and work directly on the database.

Leave a Comment