I wish to run a cron job that would permanently erase all the posts belonging to some category from the past X days (say, week). This is probably very basic, but I would appreciate some pointers. Thanks.


The first step is setting up the cron job.

The second part requires querying the database for a specific post type where the entry is older than 1 week. We can do this with get_posts() and specifying the category argument and the date_query argument.

//* If the scheduled event got removed from the cron schedule, re-add it
if( ! wp_next_scheduled( 'wpse_263953_remove_old_entries' ) ) {
  wp_schedule_event( time(), 'daily', 'wpse_263953_remove_old_entries' );

//* Add action to hook fired by cron event
add_action( 'wpse_263953_remove_old_entries', 'wpse_263953_remove_old_entries' );
function wpse_263953_remove_old_entries() {
  //* Get all posts older than 7 days...
  $posts = get_posts( [
    'numberposts' => -1,
    //* Use `cat` to query the category ID
    //* 'cat' => 'wpse_263953_category_id',
    //* Use `category_name` to query the category slug
    'category_name' => 'wpse_263953_category',
    'date_query' => [
      'after' => date( "Y-m-d H:i:s", strtotime( '-7 days', current_time( 'timestamp' ) ) ),
      //* For posts older than a month, use '-1 months' in strtotime()
  //* ...and delete them
  foreach( $posts as $post ) {
    wp_delete_post( $post->ID );
  • Thanks @Nathan. So If I wanted this to work for posts from the last week (And not from before the last week), I should replace "before" with "after"? – Tal Galili Apr 21 '17 at 6:07
  • Yes. That should work. – Nathan Johnson Apr 21 '17 at 15:06
  • 1
    You probably want to pass current_time( 'timestamp' ) as the second parameter of strtotime(), because otherwise the date will be created in reference to the GMT timezone instead of the site's timezone that the post dates are in. (Because the post_date column is used for the query, and not post_date_gmt.) – J.D. Apr 22 '17 at 15:24
  • I tried this, and it started erasing all of my posts. What should be placed in: 'category' => 'wpse_263953_category' - the category number or name? – Tal Galili Apr 22 '17 at 17:51
  • I found out the answer was to replace category with category_name – Tal Galili Apr 22 '17 at 18:22

Following Query will give you list of Post ID older than 30 days for given Category ID.

    p.ID as post_id, 
    term.term_id as category_id
FROM wp_posts as p 
LEFT JOIN wp_term_relationships as tr ON tr.object_id = p.ID
LEFT JOIN wp_terms as term ON tr.term_taxonomy_id = term.term_id
WHERE term.term_id = "CATEGORY ID HERE" 
    AND DATEDIFF(NOW(), p.post_date) > 30

Once you get the list you can decide weather you want to delete post or not.

To Delete the post use following function, the second parameter ( TRUE ) will delete the post permanently. If you want to keep the post in trash pass ( FALSE )

wp_delete_post( 'YOUR_POST_ID_HERE', TRUE);

Dont forget to change The Table prefix if its not 'wp_'

  • Thanks Jltendra. How would I run the SQL query inside php so that I'll get a variable with the posts' IDs? (so that I could loop over them for using wp_delete_post)? – Tal Galili Apr 18 '17 at 19:57
  • Click Here for a brief article on how to use custom queries in WordPress ! – JItendra Rana Apr 19 '17 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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