How to Delete Posts of a Custom Post Type Efficiently

Do you need a learn WordPress? Learn by doing now!

Sharing is caring!

How many times did you want to delete some test data?

You can paste the following snippet into your functions.php file (temporarily) or in a custom plugin.

You need to update my_custom_post_type to match your custom post type.

Then login as admin and then access your site e.g. example.com/?admin_del_cpt_posts and you’ll see the post ids as they are being deletion. So cool.

The code processes up to 250 records at a time and outputs data as soon as it’s done deleting a single record.
This is done so the server doesn’t crash due to lack of memory.

If you have more records you can just reload the page multiple times. If you really have lots of records you can adjust numberposts variable to let’s say 1000 and keep reloading.

if you’re feeling really brave then you can set it to -1 so it can process all of the records.

<?php

/**
 * Backup! This really deletes posts.
 * Data Loss Warning: This script permanently deletes data. Once executed, the deletion cannot be undone.
 * It is essential to fully understand the impact of this operation. Use this script only if you are certain that you want to
 * permanently remove the specified data.
 *
 * If you are not comfortable with scripts or if your site contains critical data, consult with a professional developer
 * or your web hosting support team before proceeding.
 * 
 * Make sure you change 'my_custom_post_type' below
 * @link https://wpsandbox.net/851
 */

//
if (isset($_REQUEST['admin_del_cpt_posts'])) {
    add_action('init', 'orb_post1234_delete_cpt_efficiently', 20);
}

/**
 * Backup! This really deletes posts.
 * @return void
 */
function orb_post1234_delete_cpt_efficiently()
{
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die("Login as admin and try again.");
    }

    /**
     * 
     * @desc
     */
    $all_posts = get_posts( array(
        'fields' => 'ids',
        'post_type' => 'my_custom_post_type',
        'numberposts' => 250,
        'post_status' => 'any',
    ) );

    ini_set('implicit_flush', 1);
    ini_set('output_buffering', 0);
    ini_set('zlib.output_compression', 0);
    header("Content-Type: text/plain");

    // https://stackoverflow.com/questions/20316338/intermittently-echo-out-data-with-long-running-php-script
    if (function_exists('apache_setenv')) {
        apache_setenv( 'no-gzip', 1 );
    }

    $total = count($all_posts);
    echo sprintf("Found: %d post(s)\n", $total);

    foreach ($all_posts as $idx => $post_id) {
        $current = $idx + 1;
        echo sprintf("[$current/$total] Deleting #%d", $post_id);

        $res = wp_delete_post( $post_id, true );

        if (empty($res)) {
            echo " failed";
        } else {
            echo " ok";
        }

        echo "\n";

        ob_flush();
        flush();
    }

    die();
}

This code is efficient because it only queries the IDs of those custom post types and then proceeds to the deletion.
We don’t need anything other than the ID.

the 2nd parameter (true) of wp_delete_post() function when true doesn’t put the deleted item in the trash where it can be restored.

Sharing is caring!

Do you need a learn WordPress? Learn by doing now!
This code shared in this post/site is provided "AS IS" without any warranties or guarantees of any kind. The authors and distributors of this code cannot be held responsible for any damage, data loss, or other issues that may arise from its use. It is strongly recommended that you test this code in a staging environment before deploying it to a live site. Always ensure you have proper backups and understand the implications of running this code on your WordPress installation. Use at your own risk.

Leave a Comment

Your email address will not be published. Required fields are marked *