Диагностика задачи: зачем и когда удалять товары без заказов
В магазине на WooCommerce может накапливаться большое количество товаров, которые никогда не были куплены. Это влияет на производительность, усложняет управление каталогом и может ухудшать пользовательский опыт. Автоматическое удаление таких товаров за выбранный период (например, 6 месяцев или год) помогает поддерживать каталог в актуальном состоянии без ручного контроля.
Как определить товары без заказов за период
Чтобы удалить товары без заказов, нужно сначала получить их список. Для этого понадобится SQL-запрос или WP_Query, объединяющий информацию из таблиц заказов WooCommerce и постов товаров.
Пример SQL-запроса для получения ID товаров без продаж за последние 6 месяцев:
SELECT p.ID FROM {$wpdb->prefix}posts p
LEFT JOIN (
SELECT order_item_meta.meta_value AS product_id
FROM {$wpdb->prefix}woocommerce_order_items order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
INNER JOIN {$wpdb->prefix}posts posts ON posts.ID = order_items.order_id
WHERE order_item_meta.meta_key = '_product_id'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ('wc-completed', 'wc-processing')
AND posts.post_date > DATE_SUB(NOW(), INTERVAL 6 MONTH)
) sold_products ON sold_products.product_id = p.ID
WHERE p.post_type = 'product'
AND sold_products.product_id IS NULL
AND p.post_status = 'publish';Этот запрос выбирает товары, у которых нет заказов со статусом wc-completed или wc-processing за последние 6 месяцев.
Пошаговое решение: автоматизация удаления через WP-Cron
1. Создаем функцию для удаления товаров без продаж
function wpbit_delete_unsold_products() {
global $wpdb;
$query = "SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN (
SELECT order_item_meta.meta_value AS product_id
FROM {$wpdb->prefix}woocommerce_order_items order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
INNER JOIN {$wpdb->posts} posts ON posts.ID = order_items.order_id
WHERE order_item_meta.meta_key = '_product_id'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ('wc-completed', 'wc-processing')
AND posts.post_date > DATE_SUB(NOW(), INTERVAL 6 MONTH)
) sold_products ON sold_products.product_id = p.ID
WHERE p.post_type = 'product'
AND sold_products.product_id IS NULL
AND p.post_status = 'publish';";
$product_ids = $wpdb->get_col($query);
if (!empty($product_ids)) {
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true); // true - удаляет без возможности восстановления
}
}
}2. Регистрируем событие WP-Cron для регулярного запуска
if (!wp_next_scheduled('wpbit_daily_delete_unsold_products')) {
wp_schedule_event(time(), 'daily', 'wpbit_daily_delete_unsold_products');
}
add_action('wpbit_daily_delete_unsold_products', 'wpbit_delete_unsold_products');3. Альтернативно: запускать вручную для теста
Для проверки можно вызвать функцию напрямую из файла темы или плагина:
add_action('init', function() {
if (current_user_can('administrator') && isset($_GET['delete_unsold'])) {
wpbit_delete_unsold_products();
echo 'Удаление товаров без заказов выполнено';
exit;
}
});Проверка результата после внедрения решения
- Посмотрите в админке WooCommerce - раздел "Товары". Товары без заказов за последние 6 месяцев должны исчезнуть.
- Проверьте, что при наличии заказов статусом
wc-completedилиwc-processingза 6 месяцев товар остается. - Для полного контроля смотрите логи (если настроены) или добавьте логирование в функцию удаления.
Частые ошибки и как их исправить
- Ошибка: Товары не удаляются — проверьте права пользователя и что WP-Cron запускается.
Решение: Удостоверьтесь, что cron-событие активировано и сервер поддерживает WP-Cron. Для отладки используйте плагин WP Crontrol. - Ошибка: Удаляются товары с заказами.
Решение: Проверьте правильность SQL-запроса и статусы заказов — могут быть другие статусы, которые нужно учитывать (например,wc-on-hold). - Ошибка: Производительность падает при большом каталоге.
Решение: Разбивайте запросы на части, используйте WP_Query с пагинацией, кешируйте результаты.
Практические советы по безопасности и производительности
- Перед удалением делайте резервные копии базы данных.
- Включайте удаление только по статусу
publish, чтобы не трогать черновики и архивные товары. - Используйте транзакции или проверяйте ошибки при удалении.
- Для больших магазинов используйте WP-CLI для запуска команд удаления вне веб-сессий.
- Добавьте логирование удаленных товаров для аудита.
Сравнение вариантов реализации удаления товаров без заказов
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| SQL-запрос + wp_delete_post + WP-Cron | Гибко, полностью под контролем, без сторонних плагинов | Требует аккуратности, знание SQL, возможны ошибки при обновлениях WooCommerce | Для разработчиков с опытом, когда нужен точный контроль |
| Плагин очистки каталога | Простота, готовое решение | Могут быть ограничения, нагрузка, меньше контроля | Для быстрого решения без программирования |
| WP-CLI скрипты | Высокая производительность, без нагрузки на сайт | Требует доступа к серверу и командной строке | Большие магазины, администраторы с SSH-доступом |