Ask your WordPress questions! Pay money and get answers fast! (more info)

Function to delete all post comments older than x days

  • SOLVED

I'm looking for a function that I can insert into any single.php or single-posttype.php theme file so that when that post is visited the function will delete all comments older than x days of the post I'm viewing.

Answers (5)

2016-12-07

dimadin answers:

You shouldn't use any of previous solutions (including that plugin) because they use direct database query, which doesn't clean comments meta table or everything else that might get cleaned on a hook. Instead, you should use some solution that uses native functions.

My example deletes all comments on 'my_post_type' that are older than 7 days, two times daily.


function md_scheduled_delete_comments() {
$comments = get_comments( array(
'post_type' => 'my_post_type',
'date_query' => array(
'before' => '7 days ago',
),
);

if ( $comments ) {
foreach ( $comments as $comment ) {
wp_delete_comment( $comment );
}
}
}
add_action( 'wp_scheduled_delete', 'md_scheduled_delete_comments' );


pjeaje comments:

Thanks, i'll test it now


pjeaje comments:

How does the scheduling work on your function? What triggers the deletion twice a day?


pjeaje comments:

HTTP ERROR 500


dimadin comments:

Sorry, I forgot to close one bracket:


function md_scheduled_delete_comments() {
$comments = get_comments( array(
'post_type' => 'my_post_type',
'date_query' => array(
'before' => '7 days ago',
),
) );

if ( $comments ) {
foreach ( $comments as $comment ) {
wp_delete_comment( $comment );
}
}
}
add_action( 'wp_scheduled_delete', 'md_scheduled_delete_comments' );


It is triggered by built in WP Cron.

Also note that some other solutions here use database query on every single page load.


pjeaje comments:

It doesn't appear to work? I've submitted a comment, then edited it's date to be much older than 7 days but the comment remains.


dimadin comments:

I just tested it and it works as expected. Maybe you didn't replace my_post_type with your post type? Maybe your have used cron and 12 hours still didn't pass? You can test it immediately by adding following line:


add_action( 'wp_loaded', 'md_scheduled_delete_comments' );


Also note that you can replace '7 days ago' to something shorter if you need to test, like '7 minutes ago', or even '30 seconds ago'.


pjeaje comments:

Maybe you didn't replace my_post_type with your post type? I did
Maybe your have used cron and 12 hours still didn't pass? Do I need to wait until 12 hours has passed before it will activate for the first time?


dimadin comments:

By default, it work only when schedule happens, that is line


add_action( 'wp_scheduled_delete', 'md_scheduled_delete_comments' );


You can make it work immediately by adding line


add_action( 'wp_loaded', 'md_scheduled_delete_comments' );


Once you confirm that this is working, you can remove second line because otherwise you'll search for old comments on each page load. That is safe to do, but there can be performance issues so you better run this less often.


pjeaje comments:

"By default, it work only when schedule happens" When does the schedule happen?


dimadin comments:

That depends on your site, but that is happening twice daily. You can use plugin WP Crontrol when is that happening and run it immediately:
https://wordpress.org/plugins/wp-crontrol/

We can also change this to different schedule, more than 12 hours or more often.


pjeaje comments:

I don't understand, how can I find out when the function will fire and delete the comments older than 7 days?


dimadin comments:

You can fire it immediately:


add_action( 'wp_loaded', 'md_scheduled_delete_comments' );


Or, you can install plugin WP Crontrol, go to the Tools -> Cron Events menu, and find "Next Run" column for 'wp_scheduled_delete'. You can also press "Run Now" in that row to fire immediately.


pjeaje comments:

I don't want to install a plugin and I don't want to fire it immediately. All I want to know is when will the code you gave me fire/action/do what i want it to do.


dimadin comments:

It's impossible for me or anyone to know that because I can't look to your database. That time is different on every single site, the only option for you is to look at your database directly or to install plugin WP Crontrol that shows that value.


pjeaje comments:

So in effect are you saying the code you gave me MAY not fire for another 12 months? In other words there is no default time for it to fire off, it just picks a random time... you need to communicate a bit better with me regarding this issue as I'm not getting the whole point of your plugin if we don't know when it will fire. I don't want to install plugins or dig into my database, I just want a function that will work.


dimadin comments:

I didn't mention 12 months, I said 12 hours.

You didn't say at what time you need it, so I suggested this because I think it's best for performance.

Even if you choose any future time, WordPress can still miss the schedule and fire at later time because that is the way WordPress and PHP work, that is not my fault, search for "wp cron", there are numerous articles on that topic if you don't believe me.

If you want guaranteed, fixed time, you must schedule this over command line, directly on your server, using system cron. Depending what hosting you are using, this might not be even possible.


pjeaje comments:

I know you didn't say 12 months but you also said "It's impossible for me or anyone to know that... "

"You didn't say at what time you need it". I said I don't want comments older than 7 days. I assume it would be fair to say the code would fire soonish after that... but you're telling me you have no idea, or is it about 12 hours? Give me an idea?

Even if you choose any future time (What are you talkingabout?), WordPress can still miss the schedule and fire at later time (define 'later') because that is the way WordPress and PHP work, that is not my fault, search for "wp cron", there are numerous articles on that topic if you don't believe me. I'm not blaming you for wp, i'm pleading with you to explain when the code will likely fire off. You're having trouble grasping my lack of understanding.


dimadin comments:

OK, here is the thing: you can leave code as is and it will fire in time that is up to 12 hours from now (depending on your site). Next time it will fire 12 hours after that. Third time it will fire 12 hours after second time. Etc. This is option number one.

Option number two: add following line, if it has comments older that 7 days, it will delete them.


add_action( 'wp_loaded', 'md_scheduled_delete_comments' );


Next time fill fire on the next page load. Then on next page load. Etc.


I think that you are not fair with me here. I suggested you clean solution, that is tested, that doesn't have bad performance on your site, unlike other bad solutions.

It's up to you what to do.


pjeaje comments:

Right... so just confirming... as the code is now... it will fire about every 12 hours and check the comments. That's fine!
My issue was never with your code just your explanation to me.

One last question... where/how did you make it every fire every 12 hours? Is this the default?


pjeaje comments:

i'll wait 12 or so hours and test it then award you.


dimadin comments:

I made it fire every 12 hours with this line:


add_action( 'wp_scheduled_delete', 'md_scheduled_delete_comments' );


This means that it fires every time this happens:


do_action( 'wp_scheduled_delete' );


And that is built-in function that is fired every 12 hours.


pjeaje comments:

And that is built-in function that is fired every 12 hours.... thanks that's all I wanted to know, WP has a default 12 hour schedule.

2016-12-07

Reigel Gallarde answers:

delete totally from database? or just for the single.php not to display it?


pjeaje comments:

From the database


pjeaje comments:

The function will need to fire before the comments load


pjeaje comments:

Or would it be easier making a function that deletes all comments of all posts of a specific post type that are x days old


Reigel Gallarde comments:

the closest hook I could find is `comments_template_query_args`

add_filter( 'comments_template_query_args', 'remove_old_comments' );
function remove_old_comments($comment_args) {
global $wpdb, $post;

if ($post->post_type == 'post') {

$date = date("Y-m-d", strtotime("-9 months") ) ;
$wpdb->query(
$wpdb->prepare(
"
DELETE FROM $wpdb->comments
WHERE comment_post_ID = %d
AND comment_date <= %s
",
$post->ID, $date
)
);

}
return $comment_args;
}


I also added the check for post type... remove it if not needed... please backup wp_comments table first before trying this... when remove, we can't put it back with no backup...


Reigel Gallarde comments:

code is badly formatted.. also pasted it here https://gist.github.com/reigelgallarde/58af092daab2bdec0ae566682c9c5387


Reigel Gallarde comments:

forgot to mention, you have to add this codes in functions.php


Reigel Gallarde comments:

I've re-read your post and found out I mistakenly put months instead of days...

change
$date = date("Y-m-d", strtotime("-9 months") ) ;
to
$date = date("Y-m-d", strtotime("-9 days") ) ;


Reigel Gallarde comments:

also works great with template_redirect hook

https://gist.github.com/reigelgallarde/a66315ae1baaef4aa0b18802441fd8fd


Reigel Gallarde comments:

have you tried this? any problem with the code?


pjeaje comments:

I'll check it soon


pjeaje comments:

When does this code action/work/fire off? On every page load?


Reigel Gallarde comments:

on before comments are loaded, as you said...

2016-12-07

Prabin Parajuli answers:

I think there is already built in plugin to delete comments completely or By selecting specific date.
https://wordpress.org/plugins/delete-all-comments-of-website/

Go to Tools -> Delete Comments. And on the Advance Filter, you can select specific dates which you want to delete your comment.

Do backup your database, though. :)


pjeaje comments:

Nice but it means I'll need to do it myself every x days. If rather it be done automatically.

2016-12-07

timDesain Nanang answers:

1. backup the database
2. put the following code in functions.php

add_action( 'wp_loaded', 'wpq_delete_comments');
function wpq_delete_comments() {
global $wpdb, $post;

if ( !is_admin() AND is_single() AND is_object($post) AND $post->post_type=='post' ) {

$days = 30; // change it
$date = date('Y-m-d H:i:s', (time() - ($days *24*60*60)));

$wpdb->query(
$wpdb->prepare(
" DELETE FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_date < %s ",
$post->ID, ''.$date.''
)
);

}
}


pjeaje comments:

Can you please comment where to change the post type, with an example


timDesain Nanang comments:

sure

add_action( 'wp_loaded', 'wpq_delete_comments');
function wpq_delete_comments() {
global $wpdb, $post;

$days = 30; // days => change it
$my_cpt = 'your_custom_post_type'; // change with your custom post type

if ( !is_admin() AND is_single() AND is_object($post) AND $post->post_type==$my_cpt ) {

$date = date('Y-m-d H:i:s', (time() - ($days *24*60*60)));

$wpdb->query(
$wpdb->prepare(
" DELETE FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_date < %s ",
$post->ID, ''.$date.''
)
);

}
}


pjeaje comments:

When does this code action/work/fire off? On every page load?


timDesain Nanang comments:

yep, every page load, if the following conditions are met:
1. not in admin area (/wp-admin/)
2. in single post of 'your_custom_post_type'

'wp' action hook runs immediately after the global WP class object is set up. The $wp object is passed to the hooked function as a reference (no return is necessary).
This hook is one effective place to perform any high-level filtering or validation, following queries, but before WordPress does any routing, processing, or handling.

https://codex.wordpress.org/Plugin_API/Action_Reference/wp

2016-12-07

Luis Abarca answers:

You may use somehting like this.

<?php

function delete_comments($date)
{
global $wpdb;

$table = $wpdb->prefix . 'comments';

$sql = sprintf("DELETE FROM %s, WHERE comment_date < '%s'", $table, $date);
}

function delete_post_comments($post_id, $date)
{
global $wpdb;

$table = $wpdb->prefix . 'comments';

$sql = sprintf("DELETE FROM %s, WHERE comment_post_ID = %d AND comment_date < '%s'", $table, $post_id, $date);
}

// Delete all comments from last month
delete_comments('2016-11-01');

// Delete all comments from last month from post 1
delete_comments(1, '2016-11-01');