Диагностика проблемы: зачем и когда удалять незаконченные товары
В WooCommerce под "незаконченные товары" часто понимаются товары, которые были созданы, но не добавлены в заказы, либо товары, которые хранятся в статусе "черновик" или "отменённый заказ". В ряде случаев магазин наполняется такими товарами из-за ошибок импорта, тестирования или некорректных плагинов. Это замедляет работу сайта, увеличивает размер базы и усложняет администрирование.
Проверить наличие таких товаров можно через SQL-запрос или стандартный фильтр в админке WooCommerce:
SELECT ID, post_title, post_status FROM wp_posts WHERE post_type = 'product' AND post_status IN ('draft', 'pending', 'auto-draft');Или в админке: Товары –> Все товары –> Использовать фильтр по статусу "Черновик" или "Ожидает проверки".
Пошаговое решение: удаление товаров по дате и статусу через код
1. Создание кастомной функции для удаления
Добавьте следующий код в файл functions.php активной темы или в отдельный плагин для кастомных функций.
function delete_woocommerce_products_by_status_and_date( $status = 'draft', $date_before = '' ) {
if ( empty( $date_before ) ) {
return;
}
$args = array(
'post_type' => 'product',
'post_status' => $status,
'date_query' => array(
array(
'before' => $date_before,
'inclusive' => true,
),
),
'posts_per_page' => -1,
'fields' => 'ids',
);
$query = new WP_Query( $args );
if ( ! empty( $query->posts ) ) {
foreach ( $query->posts as $product_id ) {
wp_delete_post( $product_id, true ); // true - без перемещения в корзину
}
}
}2. Запуск функции с параметрами
Например, чтобы удалить все товары со статусом "черновик", созданные до 1 января 2024 года:
add_action( 'init', function() {
// Удаляем товары со статусом 'draft', созданные до 2024-01-01
delete_woocommerce_products_by_status_and_date( 'draft', '2024-01-01' );
} );Обратите внимание: функцию лучше запускать однократно, после удаления — закомментировать или удалить вызов.
Проверка результата после внедрения
- Перейдите в админку WooCommerce: Товары – проверьте, что товары со статусом и датой удаления отсутствуют.
- Выполните SQL-запрос из раздела диагностики — убедитесь, что записи удалены.
- Проверьте загрузку страниц с товарами — должна улучшиться при значительном количестве удалённых записей.
Частые ошибки и как их исправить
- Функция не удаляет товары: Проверьте правильность статуса и даты, убедитесь, что хук
initсрабатывает. Для отладки временно добавьтеerror_logвнутри цикла. - Удаление не происходит полностью: Если товары связаны с вариациями, нужно удалять все вариации, иначе останутся дочерние записи.
- Потеря данных из-за случайного запуска: Запуск кода на боевом сайте без теста может привести к удалению нужных товаров. Используйте условие, например, проверку IP или nonce.
Практические советы для безопасности и производительности
- Перед запуском сделайте резервную копию базы данных.
- Используйте
wp_delete_postс параметромtrueдля полного удаления без корзины. - Если товаров очень много, разбивайте удаление на части, чтобы избежать таймаута сервера.
- Для планового удаления можно использовать WP-Cron или WP CLI с аналогичной функцией.
Дополнительные возможности: удаление товаров по статусу и дате с учётом вариаций
Для удаления вариаций добавьте следующий код в функцию:
foreach ( $query->posts as $product_id ) {
$children = get_posts( array(
'post_type' => 'product_variation',
'post_parent' => $product_id,
'fields' => 'ids',
'posts_per_page' => -1,
) );
foreach ( $children as $child_id ) {
wp_delete_post( $child_id, true );
}
wp_delete_post( $product_id, true );
}Сравнение методов удаления незаконченных товаров
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| Удаление через админку | Просто, без кода | Медленно, неудобно при большом объёме | Фильтр по статусу → массовое удаление |
| Код на PHP (wp_delete_post) | Автоматизация, гибкость | Риск ошибок, нужен тест | Функция delete_woocommerce_products_by_status_and_date |
| SQL-запрос напрямую (DELETE) | Очень быстро | Риск повреждения базы, нужно удалять метаданные вручную | DELETE FROM wp_posts WHERE post_type='product' AND post_status='draft' AND post_date < '2024-01-01' |