Диагностика задачи: зачем удалять неактивные товары
Магазины на WooCommerce часто сталкиваются с проблемой накопления товаров, которые давно не продаются и не обновлялись. Это замедляет работу сайта, увеличивает нагрузку на базу данных и усложняет управление каталогом. Автоматическое удаление таких товаров помогает поддерживать актуальность ассортимента и улучшает производительность.
Определение критериев неактивного товара
Для автоматизации важно чётко задать критерии, по которым товар считается неактивным:
- Отсутствие продаж за определённый период (например, 6 месяцев);
- Дата последнего обновления товара старше заданного срока;
- Товар не находится в статусе «черновик» или «в ожидании» (то есть опубликован).
В WooCommerce продажи фиксируются через записи заказов, а дата обновления товара хранится в post_modified.
Пошаговое решение: код для автоматического удаления неактивных товаров
Ниже пример функции, которую можно добавить в functions.php или создать небольшой плагин. Функция будет запускаться по расписанию и удалять товары, не продававшиеся более 180 дней.
<?php
// Создаём событие Cron при активации плагина или темы
if (!wp_next_scheduled('wc_delete_inactive_products_event')) {
wp_schedule_event(time(), 'daily', 'wc_delete_inactive_products_event');
}
// Хук на выполнение события
add_action('wc_delete_inactive_products_event', 'wc_delete_inactive_products');
function wc_delete_inactive_products() {
global $wpdb;
$threshold_days = 180; // 180 дней без продаж
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$threshold_days} days"));
// Получаем ID продуктов, которые:
// 1) опубликованы
// 2) не продавались после $date_threshold
// 3) обновлялись до $date_threshold
$query = $wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND p.post_modified < %s
AND p.ID NOT IN (
SELECT DISTINCT order_item_meta.meta_value
FROM {$wpdb->prefix}woocommerce_order_items as order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
INNER JOIN {$wpdb->posts} as orders ON orders.ID = order_items.order_id
WHERE order_item_meta.meta_key = '_product_id'
AND orders.post_status IN ('wc-completed', 'wc-processing')
AND orders.post_date >= %s
)",
$date_threshold,
$date_threshold
);
$product_ids = $wpdb->get_col($query);
if (empty($product_ids)) {
return; // Нет товаров для удаления
}
foreach ($product_ids as $product_id) {
wp_trash_post($product_id); // Отправляем товар в корзину для удаления
}
}
// Для очистки cron при деактивации
register_deactivation_hook(__FILE__, function() {
wp_clear_scheduled_hook('wc_delete_inactive_products_event');
});
Проверка результата после внедрения
Чтобы убедиться, что удаление работает:
- Добавьте временный лог в функцию
wc_delete_inactive_products, например, черезerror_log(), чтобы видеть, какие ID удаляются. - Запустите событие вручную, вызвав
do_action('wc_delete_inactive_products_event');через консоль WP-CLI (wp eval 'do_action("wc_delete_inactive_products_event");'). - Проверьте, что товары, соответствующие критериям, переместились в корзину (Trash) в админке WooCommerce.
Частые ошибки и их исправление
- Ничего не удаляется: возможно, условие выборки не срабатывает из-за неверного формата дат или статусов заказов. Проверьте, что заказы имеют статусы
wc-completedилиwc-processing. - Удаляются нужные товары: проверьте правильность условия на дату обновления и продажи, можно временно увеличить период или вывести список ID для проверки.
- Проблемы с производительностью при большом каталоге: разбейте удаление на порции, добавьте лимит в SQL-запрос или используйте транзакции.
Практические советы для безопасности и производительности
- Всегда используйте
wp_trash_post(), чтобы иметь возможность восстановить товар из корзины, а не удаляйте сразу навсегда. - Запускайте удаление в ночное время через Cron, чтобы не нагружать сервер в часы пик.
- Перед массовым удалением сделайте резервную копию базы данных.
- Добавьте логирование удалённых товаров в отдельный файл для аудита.
- Для больших магазинов используйте пагинацию в запросе и удаляйте партиями, например по 50 товаров за одну итерацию.
Сравнение вариантов автоматического удаления неактивных товаров
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Плагин автоматизации | Удобный интерфейс, поддержка | Может быть тяжёлым, платным | Использовать проверенные плагины с минимальным функционалом |
| Код в functions.php | Лёгкий, кастомный, без нагрузки | Требует навыков, нет интерфейса | Добавить простой лог и возможность включать/выключать через опцию |
| Удаление вручную через админку | Безопасно, контролируемо | Трудозатратно, не автоматично | Использовать для мелких магазинов или точечных случаев |