wordpresscode-snippetsvscode-snippets

Auto delete old posts using Snippets for special category


Dears,

I want to delete the old post automatically without using a plugin and the Snippets will be the choice, I want to delete any post older than one day from a special category an using this Snippet but nothing deleted:

// Automatically delete posts older than x days
function delete_old_posts($category_id = 62) {
    $days = 1; // Change this value to the desired number of days
    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => -1,
        'date_query'     => array(
            array(
                'before' => $days . ' days ago',
                'inclusive' => true,
            ),
        ),
    'tax_query' => array(
      array(
        'taxonomy' => 'slug', // Replace 'category' with your actual taxonomy slug if different
        'field' => 'id',
        'terms' => array($category_id), // Array of category IDs to target
      ),
    ),
    );
    $old_posts = new WP_Query($args);

    if ($old_posts->have_posts()) :
        while ($old_posts->have_posts()) : $old_posts->the_post();
            wp_delete_post(get_the_ID(), true);
        endwhile;
    endif;
    wp_reset_postdata();
}
add_action('wp', 'delete_old_posts');

Solution

  • TLDR;

    Grab the te_delete_old_posts() function if using independently and no need for the cron parts if that is not required.

    // Function to set up a daily custom event.
    function te_setup_daily_post_deletion_event() {
        if (!wp_next_scheduled('te_daily_post_deletion_hook')) {
            wp_schedule_event(time(), 'daily', 'te_daily_post_deletion_hook');
        }
    }
    add_action('wp', 'te_setup_daily_post_deletion_event');
    
    // Function to delete old posts.
    function te_delete_old_posts() {
        $category_id = 62; // Set your category ID.
       
        $days = 1; // Posts older than this number of days will be deleted.
    
        $query_date = date('Y-m-d', strtotime("-$days days"));
    
        $args = array(
            'post_type'      => 'post',
            'posts_per_page' => -1,
            'fields'         => 'ids', // Retrieve only the IDs for efficiency.
            'date_query'     => array(
                array(
                    'before' => $query_date,
                    'inclusive' => false, // set to true if previous day is considered a day old
                ),
            ),
            'tax_query' => array(
                array(
                    'taxonomy' => 'category',
                    'field'    => 'term_id',
                    'terms'    => array($category_id),
                ),
            ),
        );
    
        $old_posts = get_posts($args); // Get a nice lean memory efficient list of post ID's
    
        if (!empty($old_posts)) {
            foreach ($old_posts as $post_id) {
                wp_delete_post($post_id, true);
            }
        }
    }
    // Used for the cronjob method
    add_action('te_daily_post_deletion_hook', 'te_delete_old_posts');
    

    Make sure your Query returns the required result:

    In the example below I extracted the main query component so you can add to a function and run it.

    The date initially passed does not come out as expected. $query_date is used to get the correct date using PHP date/strtotime functions with no time residue.

    Also I am telling the query to provide only ID's of the results so that it will be efficient than getting entire post objects.

    Finally I am using get_posts() so that we can get an clean array of Post ID's to loop thru, and not have to deal with WP_Query().

        $category_id = 62; // Set your category ID.
       
        $days = 1; // Posts older than this number of days will be deleted.
    
        $query_date = date('Y-m-d', strtotime("-$days days"));
    
        $args = array(
            'post_type'      => 'post',
            'posts_per_page' => -1,
            'fields'         => 'ids', // Retrieve only the IDs for efficiency.
            'date_query'     => array(
                array(
                    'before' => $query_date,
                    'inclusive' => false, // set to true if previous day is considered a day old
                ),
            ),
            'tax_query' => array(
                array(
                    'taxonomy' => 'category',
                    'field'    => 'term_id',
                    'terms'    => array($category_id),
                ),
            ),
        );
    
        $old_posts = get_posts($args); // Get array of post ID's
    
        if (!empty($old_posts)) {
            foreach ($old_posts as $post_id) {
               echo $post_id . " " get_the_title($post_id);
            }
        }
    

    Running just this code you can verify that you are getting the expected results, and tweak the query if not.

    Is this a Recurring event:

    If this process is a recurring event which it sounded like from the description. It should go in WP cronjob so that the process does not keep running each time a page loads as you had in the 'wp' hook. I am guessing that must have been for testing or you were planning on doing this manually.

    function te_setup_daily_post_deletion_event() {
        if (!wp_next_scheduled('te_daily_post_deletion_hook')) {
            wp_schedule_event(time(), 'daily', 'te_daily_post_deletion_hook');
        }
    }
    add_action('wp', 'te_setup_daily_post_deletion_event');
    

    Running with WP-CLI

    If you do not wish to use a cronjob and want to run this manually, add the function te_delete_old_posts() in your themes function.php or in a custom plugin and you can use one of the two methods bellow to run the function.

    wp eval "te_delete_old_posts();"
    

    Hit enter after typing the function name inside the shell

    wp shell
    wp> te_delete_old_posts()
    

    Always use wp_delete_post() to delete Posts:

    Your script is a pretty good start, and you seemed to be on the right track. WordPress creates data in a few tables when you create a posts and it is important that proper cleanup happens when you delete a post. wp_delete_post() does just that.

    And as mentioned use the code I provided for testing and make sure you are getting results first, if something is not working.