4

I feel like this should be a simple question, but I can't figure it out.

If I have a post_id, how can I remove a particular tag from that post in php?? I know how to update meta information, but tag information is different.

2
  • Did you mean remove a tag's association with a post? As in, it was tagged 'music' or 'art' and you want to un-tag it?
    – miahelf
    Commented Apr 17, 2012 at 5:52
  • Yes. That is what I mean. Commented Apr 17, 2012 at 6:19

3 Answers 3

4

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.

1
  • 1
    Unfortunately, quite a lot of Wordpress is undocumented for whatever reason. Sounds like that is the right tool for the job to me. Setting to uncategorized only applies to categories, having no tags is not a problem. The only other solution I can think of would be a raw MySQL query to change the term_relationships table, which seems worse than that function you found.
    – miahelf
    Commented Apr 17, 2012 at 7:04
1

For whatever reason, Alexander Bird's routine didn't quite work for me. I modified it a little to use wp_set_post_tags instead of wp_set_object_terms:

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) {
        $curtags = wp_get_post_tags($post_id, 'post_tag');
        $newtags = array();
        foreach($tags as $tag) {
            foreach($curtags as $id=>$curtag) {
                if ( $curtag->name == $tag ) {
                    unset($curtags[$id]);
                }
            }
        }

        foreach ($curtags as $curtag) {
            $newtags[] = $curtag->name;
        }

        wp_set_post_tags( $post_id, $newtags, false );
    }
}
0

wp_remove_object_terms($post_id, 'your_tag_name', 'tags');

Will dot the job.

See https://developer.wordpress.org/reference/functions/wp_remove_object_terms/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.