remove tags from posts in php

Below is code that works:

function untag_posts($post_ids, $tags) {
    global $wpdb;
    if(! is_array($post_ids) ) { 
        $post_ids = array($post_ids);
    }   
    $in_post_ids = implode("','", $post_ids);

    if(! is_array($tags) ) { 
        $tags = array($tags);
    }   
    $in_tag_names = "'" . implode("','", $tags) . "'";

    $query = "SELECT tt.term_taxonomy_id " . 
        " from $wpdb->terms as t " . 
            " JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id " . 
            " JOIN $wpdb->term_relationships as tr on tr.term_taxonomy_id = tt.term_taxonomy_id " . 
        " where t.name in ($in_tag_names) " . 
            " AND (tr.object_id in ($in_post_ids)) ";
    $tt_ids = $wpdb->get_col($query); // TODO: correct function?
    $in_tt_ids = implode("','", $tt_ids);

    $delete_query = "DELETE FROM $wpdb->term_relationships where object_id in ($in_post_ids) and term_taxonomy_id in ($in_tt_ids)";
    $myrows = $wpdb->get_results( $delete_query );
}

Below is an alternate code which works:

function untag_post($post_ids, $tags) {
    global $wpdb;
    if(! is_array($post_ids) ) {
        $post_ids = array($post_ids);
    }
    if(! is_array($tags) ) {
        $tags = array($tags);
    }

    foreach($post_ids as $post_id) {
        $terms = wp_get_object_terms($post_id, 'post_tag');
        $newterms = array();
        foreach($terms as $term) {
            if ( !in_array($term->name,$tags) ) { //$term will be a wordpress Term object.
                $newterms[] = $term;
            }
        }
        wp_set_object_terms($post_id, $newterms, 'post_tag', FALSE);
    }
}

Below is the test data I used within the wordpress test environment (http://codex.wordpress.org/Automated_Testing) to test the functions:

function test_untag_post() {
    function untag_post($post_ids, $tags) {
        global $wpdb;
        if(! is_array($post_ids) ) { 
            $post_ids = array($post_ids);
        }   
        if(! is_array($tags) ) { 
            $tags = array($tags);
        }   

        foreach($post_ids as $post_id) {
            $terms = wp_get_object_terms($post_id, 'post_tag');
            $newterms = array();
            foreach($terms as $term) {
                if ( !in_array($term->name,$tags) ) { //$term will be a wordpress Term object.
                    $newterms[] = $term;
                }   
            }   
            wp_set_object_terms($post_id, $newterms, 'post_tag', FALSE);
        }   
    }   
    $post = array();
    $post['post_content'] = "Here is some content.";
    $post['post_excert'] = "Quick excerpt.";
    $post['post_title'] = "Test Post";
    $post['post_name'] = "test-post";
    $post['post_type'] = "post";
    $post_id = wp_insert_post($post);

    wp_add_post_tags($post_id, 'test-tag');
    $terms = wp_get_object_terms($post_id, 'post_tag');
    $this->assertEquals('test-tag', $terms[0]->name);

    untag_post($post_id, 'test-tag');

    $terms = wp_get_object_terms($post_id, 'post_tag');
    $this->assertEmpty($terms);
} 

EDIT: The below (which was my previous answer) IS WRONG

All that my previous answer would allow is a way to remove all post tags. But I am looking for a way to remove only specific post tags.


The function wp_delete_object_term_relationships (wp-includes/taxonomy.php line 1662) is a low level function that will do this. However…

  1. it doesn’t automatically put something as uncategorized if needed (which may not be a problem)

  2. I have not tested this

  3. I feel a little uncomfortable using low level functions that are not mentioned on wordpress doc website as intended for public use.

So perhaps there is a better way.

Leave a Comment