Delete expired posts after a number of days after they expired

WP Cron jobs are not reliable as it needs someone to visit the site at the time the event should fire. If you need precise timing, you should use server cron jobs.

Anyways, lets look at your code and what is wrong and we can fix it

  • wp is a better hook to use to hook your scheduled event, this is the earliest that postdata available. init is way to early. I probably think for safety, you can also try the template_redirect hook.

  • Your code are very very expensive to run which unnecessarily wastes server resources. We need to look at the following:

    • We do not need any postdata except the post ID. Any other postdata are useless, and querying it waste a lot of resources. On large sites, this can actually lead to fatal errors due to timing out

    • We only need to query posts which has expired and the expiry date has reached a certain timeframe.

Lets put everything in code: (NOTE: This all untested, I have also copied and pasted some of your code, so I might have missed something, and also, the code requires PHP 5.4+)

function get_exired_posts_to_delete()
{
    /**
     * If you need posts that expired more than a week ago, we would need to
     * get the unix time stamp of the day a week ago. You can adjust the relative 
     * date and time formats as needed. 
     * @see http://php.net/manual/en/function.strtotime.php
     * @see http://php.net/manual/en/datetime.formats.php
     */
    // As example, we need to get posts that has expired more than 7days ago
    $past = strtotime( "- 1 week" );

    // Set our query arguments
    $args = [
        'fields'         => 'ids', // Only get post ID's to improve performance
        'post_type'      => 'advert',
        'post_status'    => 'expired',
        'posts_per_page' => -1,
        'meta_query'     => [
            [
                'key'     => '_expiration_date',
                'value'   => $past,
                'compare' => '<='
            ]
        ]
    ];
    $q = get_posts( $args );

    // Check if we have posts to delete, if not, return false
    if ( !$q )
        return false;

    // OK, we have posts to delete, lets delete them
    foreach ( $q as $id )
        wp_delete_post( $id );
}

Now we can create our custom hook to hook our function

// expired_post_delete hook fires when the Cron is executed
add_action( 'expired_post_delete', 'get_exired_posts_to_delete' );

Lastly, schedule our event

// Add function to register event to wp
add_action( 'wp', 'register_daily_post_delete_event');
function register_daily_post_delete_event() {
    // Make sure this event hasn't been scheduled
    if( !wp_next_scheduled( 'expired_post_delete' ) ) {
        // Schedule the event
        wp_schedule_event( time(), 'daily', 'expired_post_delete' );
    }
}

This should about do it, just remember to set the correct time frame inside the function

Leave a Comment