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.
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.
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...
it doesn't automatically put something as uncategorized if needed (which may not be a problem)
I have not tested this
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.
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 );
}
}
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/