Иногда в проектах на WordPress возникает необходимость массово удалить записи, основываясь на значениях пользовательских мета-полей (custom fields). Например, вы хотите удалить все посты, у которых в мета-поле wp_element_status стоит значение archived. В стандартной админке WordPress такой функции нет. В этой статье мы подробно рассмотрим, как решить эту задачу программно, используя WP_Query и функции удаления.
Почему удаление по мета-полю — полезная задача для разработчиков WordPress
Пользовательские мета-поля — мощный инструмент для хранения дополнительной информации о записях. Часто именно они определяют логику отображения, фильтрации и управления контентом. Однако после завершения проекта или при рефакторинге контента может потребоваться массовое удаление записей, соответствующих определённому условию по мета-данным.
Ручное удаление через админку неудобно, особенно если записей много. Скрипт, который мы разберём, позволит автоматизировать процесс, минимизируя ошибки и экономя время.
Подготовка к удалению: создание безопасного WP_Query по мета-полю
Для начала формируем выборку записей с нужным мета-условием. Здесь важно учитывать производительность и безопасность.
Пример запроса, который извлекает записи с meta_key = 'wp_element_status' и meta_value = 'archived':
$args = [
'post_type' => 'post',
'meta_query' => [
[
'key' => 'wp_element_status',
'value' => 'archived',
'compare' => '=',
],
],
'posts_per_page' => -1, // получить все записи
'fields' => 'ids' // для экономии памяти возвращаем только ID
];
$query = new WP_Query($args);
Параметр fields => 'ids' позволяет получить массив ID записей без лишних данных, что критично при большом количестве постов.
Особенности и ограничения запроса
Стоит помнить, что мета-запросы могут сильно нагрузить базу, если таблица wp_postmeta не оптимизирована. Рекомендуется перед массовыми операциями убедиться, что в базе есть индексы по мета-ключам.
Кроме того, если записей очень много, можно разбить удаление на чанки, чтобы избежать превышения лимитов по памяти и времени выполнения.
Удаление записей по ID: использование функции wp_element_delete_posts_by_meta()
Создадим функцию, которая принимает мета-ключ и мета-значение, и удаляет все соответствующие записи. Важно использовать встроенную функцию WordPress wp_delete_post(), чтобы корректно удалить все данные, связанные с постом (комментарии, мета, кэш).
function wpelement_delete_posts_by_meta($meta_key, $meta_value) {
$args = [
'post_type' => 'post',
'meta_query' => [
[
'key' => $meta_key,
'value' => $meta_value,
'compare' => '=',
],
],
'posts_per_page' => -1,
'fields' => 'ids',
'no_found_rows' => true,
];
$query = new WP_Query($args);
if (empty($query->posts)) {
return 'Записи для удаления не найдены.';
}
foreach ($query->posts as $post_id) {
// Удаляем пост без перемещения в корзину
wp_delete_post($post_id, true);
}
return count($query->posts) . ' записей успешно удалено.';
}
Эту функцию удобно запускать из консоли WP-CLI или вызывать по хуку в админке, например через кастомную страницу или ajax-запрос.
Безопасность и проверка прав
Перед удалением обязательно проверяйте, что текущий пользователь имеет права на удаление записей, чтобы избежать непреднамеренного удаления:
if (!current_user_can('delete_posts')) {
return 'У вас нет прав для удаления записей.';
}
Пример использования: удаляем все посты со статусом 'archived'
Запустим функцию с конкретными параметрами:
echo wpelement_delete_posts_by_meta('wp_element_status', 'archived');
После выполнения все записи с этим мета-полем будут удалены безвозвратно.
Разбивка удаления на части: как избежать таймаутов и ошибок памяти
Если записей очень много, лучше удалять порциями. Например, по 50 записей за один вызов:
function wpelement_delete_posts_by_meta_chunked($meta_key, $meta_value, $chunk_size = 50) {
$paged = 1;
$total_deleted = 0;
do {
$args = [
'post_type' => 'post',
'meta_query' => [
[
'key' => $meta_key,
'value' => $meta_value,
'compare' => '=',
],
],
'posts_per_page' => $chunk_size,
'paged' => $paged,
'fields' => 'ids',
'no_found_rows' => true,
];
$query = new WP_Query($args);
if (empty($query->posts)) {
break;
}
foreach ($query->posts as $post_id) {
wp_delete_post($post_id, true);
$total_deleted++;
}
$paged++;
// Можно добавить паузу, если надо
// sleep(1);
} while (count($query->posts) === $chunk_size);
return $total_deleted . ' записей удалено по частям.';
}
Этот подход снижает нагрузку на сервер и позволит обработать тысячи записей без перебоя.
Заключение: когда и зачем использовать удаление по мета-полю
Удаление записей по мета-полю — полезный инструмент при управлении большим объемом контента, особенно если вы используете кастомные статусы, метки или другие данные в мета. Это позволяет быстро очищать базу от устаревших или неактуальных записей.
Внимательно тестируйте скрипты на тестовом сервере и обязательно делайте резервные копии базы перед выполнением массовых операций удаления.
Если вы хотите автоматизировать такие задачи регулярно, рассмотрите возможность интеграции с WP-CLI или созданием кастомных инструментов в админке.