Eliminar todas las entradas del Blog por código

Delete Posts

Hay ocasiones en las que realizamos pruebas de importaciones y entre las diversas acciones que realizamos solemos acabar con un WordPress lleno de entradas que debemos vaciar seleccionándolas en lote y es un proceso tedioso y lento.

Podemos eliminar fácilmente todas las entradas de la tabla de posts con una simple consulta SQL, pero nos seguirán quedando muchos datos en la tabla postmeta. Si, se puede eliminar sin complicaciones añadiendo un JOIN entre tablas, pero ¿y si es multiidioma y tenemos relaciones en otras tablas? ¿Y los datos de YOAST o Rank Math? ¿Los campos adicionales?….

En todos estos casos si el plugin está bien desarrollado (que ya os digo que tristemente no es en la mayoría de los casos), se «enganchará» en los hooks adecuados de los eventos de borrado del post para también borrar sus datos relativos.

Debido a esto, la mejor opción para borra una entrada de WordPress es utilizar su función nativa, que ejecuta sus hooks y en los que se ejecutarán las acciones oportunas.

La función nativa de borrado de posts es wp_delete_post() a la que le pasamos el ID de la entrada y si de segundo parámetro le pasamos true, la elimina definitivamente sin llevarla a la papelera. Cuidado con esto último, porque si borramos Custom Post Types, aunque le pasemos false de segundo parámetro, la eliminará definitivamente, por lo que si queremos enviar estas entradas a la papelera, será mejor utilizar wp_trash_post().

Como lo que queremos es eliminar entradas del bog (posts) utilizaremos la función get_posts().

En el array de argumentos que le pasamos, usamos numberposts con -1 para recuperar todas las entradas. Si fuesen muchas (10.000 por ejemplo), podemos irlo ejecutando con 1.000 entradas e irlas borrando «en lotes», ya que dependiendo de la instalación, puede que en los hooks del borrado se ejecuten muchas acciones.

El script es el siguiente:

<?php
die( 'Carlos says that silence is golden' );

require_once( '../wp-load.php' );

$website_posts = get_posts( array( 'numberposts' => -1 ) );

echo '<ol>';
foreach ( $website_posts as $post ) {
	// Delete all posts.
	wp_delete_post( $post->ID, true ); // Set to False if you want to send them to Trash.
	echo '<li>Post deleted (type: "' . $post->post_type . '", status: ' . $post->post_status . '; ID: ' . $post->ID . ') with title «' . $post->post_title . '»</li>';
}
echo '</ol>';

Desde luego que tienes que saber lo que hace la primera línea para que funcione el script, si no lo sabes, entonces abstente de copiarlo y ejecutarlo, ya que puede ser muy peligroso para tu instalación.

Este script lo subo a una carpeta en la raíz de la instalación, de ahí que el require_once suba un nivel para cargar el core base de WordPress.

En la línea 6 como ya he comentado, podemos cargar solo un número determinado de posts a borrar o por ejemplo seleccionar páginas añadiéndole al array 'post_type' => 'page' o los productos de WooCommerce con 'post_type' => 'product', nuestro CPT y otras personalizaciones.

Después creo una lista ordenada para que el propio HTML me vaya numerando cada entrada eliminada junto con una serie de datos que muestro, como su ID, título, etc.

En la línea 11 donde ejecutamos el wp_delete_post() podemos realizar alguna comprobación como que el $post->post_status sea wc-completed si habíamos elegido 'post_type' => 'shop_order' para así eliminar todos los pedidos completados (o con otra condición más solo los de más de x años, etc.).

Como podemos ver es un script muy sencillo, que podemos personalizar todo lo que queramos, pero CUIDADO, también ES MUY PELIGROSO. Realiza siempre copias de seguridad y tan pronto acabes de usarlo ELIMÍNALO o al menos deja presente la línea del die() no vaya a ser que alguien lo ejecute por ti cuando ya no estés en pruebas. 🙁

Actualización del 3/9/2021: Luis Ruiz acaba de publicar un excelente artículo en el que explica como eliminar solo algunas urls en lugar de todas, para lo que se crea un archivo CSV con las URL a eliminar y el script se encarga del resto. Gracias, Luis.

Date de alta en mi superlista ;)

No compartiré tus datos con nadie ni te bombardearé a correos, solo cuando publique una nueva entrada o cuando tenga algo interesante que compartir contigo.

Deja un comentario