Диагностика проблемы: зачем удалять неактивные товары в WooCommerce
В крупных интернет-магазинах на WooCommerce со временем накапливаются товары, которые не продаются, не обновляются и занимают место в базе данных. Это может замедлить работу сайта, усложнить администрирование и ухудшить пользовательский опыт. Ручное удаление таких товаров — утомительный и рискованный процесс. Автоматизация удаления позволит поддерживать каталог в актуальном состоянии без лишних затрат времени.
Как определить неактивные товары для удаления
Основные критерии для определения неактивных товаров:
- Отсутствие продаж за заданный период (например, 6 месяцев);
- Отсутствие обновлений или изменений метаданных за тот же период;
- Статус товара — опубликовать (publish), чтобы не удалять черновики и архивы;
- Отсутствие связанных заказов с завершенным статусом.
В WooCommerce данные о продажах хранятся в мета-данных заказов, что требует дополнительной проверки.
Пошаговое решение: настройка автоматического удаления неактивных товаров
1. Создаем функцию для поиска и удаления неактивных товаров
Код ниже ищет товары, которые не продавались и не обновлялись более 180 дней, и удаляет их безопасно.
function wpsell_delete_inactive_products() {
$days_inactive = 180; // Период неактивности в днях
$date_threshold = date('Y-m-d H:i:s', strtotime('-' . $days_inactive . ' days'));
// Получаем ID товаров, обновленных до пороговой даты
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'date_query' => [
[
'column' => 'post_modified',
'before' => $date_threshold,
],
],
'fields' => 'ids',
'posts_per_page' => -1,
];
$products = get_posts($args);
if (empty($products)) {
return; // Нет товаров для удаления
}
global $wpdb;
foreach ($products as $product_id) {
// Проверяем наличие завершенных заказов с этим товаром
$order_ids = $wpdb->get_col($wpdb->prepare(
"SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items oi
JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
JOIN {$wpdb->prefix}posts p ON p.ID = oi.order_id
WHERE oi.order_item_type = 'line_item'
AND oim.meta_key = '_product_id' AND oim.meta_value = %d
AND p.post_status IN ('wc-completed', 'wc-processing')",
$product_id
));
if (empty($order_ids)) {
// Нет продаж — удаляем товар
wp_delete_post($product_id, true); // true - полное удаление без корзины
}
}
}2. Регистрируем WP-Cron задачу для регулярного запуска
Добавим запуск функции один раз в сутки.
function wpsell_schedule_inactive_products_deletion() {
if (!wp_next_scheduled('wpsell_delete_inactive_products_hook')) {
wp_schedule_event(time(), 'daily', 'wpsell_delete_inactive_products_hook');
}
}
add_action('wp', 'wpsell_schedule_inactive_products_deletion');
add_action('wpsell_delete_inactive_products_hook', 'wpsell_delete_inactive_products');3. Отменяем задание при деактивации плагина или темы
function wpsell_clear_inactive_products_deletion_schedule() {
$timestamp = wp_next_scheduled('wpsell_delete_inactive_products_hook');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wpsell_delete_inactive_products_hook');
}
}
register_deactivation_hook(__FILE__, 'wpsell_clear_inactive_products_deletion_schedule');Проверка результата после внедрения
- Запустите функцию вручную с помощью
wpsell_delete_inactive_products()в консоли WP-CLI или временно вызовите ее в functions.php и проверьте удаление товаров. - Проверьте наличие товаров с датой обновления больше 180 дней в админке (через фильтр по дате изменения).
- Просмотрите логи ошибок и убедитесь, что wp_delete_post срабатывает без ошибок.
- Проверьте, что товары с завершенными заказами не удаляются.
Частые ошибки и как их исправить
- Удаляются товары с активными заказами: ошибка в запросе проверки заказов. Проверьте правильность JOIN и статусов заказов (wc-completed, wc-processing).
- Функция не запускается по расписанию: убедитесь, что WP-Cron работает (нет проблем с вызовом wp-cron.php). Для теста можно использовать плагин WP Crontrol.
- Удаление не происходит: проверьте права пользователя, под которым запускается скрипт, и наличие ошибок в логах PHP.
- Высокая нагрузка на базу при выполнении: ограничьте количество товаров на удаление за один запуск, например, добавьте параметр
'posts_per_page' => 50и используйте пагинацию.
Практические советы по безопасности и производительности
- Перед удалением рекомендуется создавать резервные копии базы данных.
- Для больших магазинов лучше выполнять удаление пакетами, чтобы не блокировать базу длительное время.
- Используйте транзакции или проверяйте целостность данных после удаления.
- Отключайте задачу WP-Cron на пиковых нагрузках сайта, чтобы избежать замедлений.
Сравнение вариантов реализации автоматического удаления товаров
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Самописный код с WP-Cron | Полный контроль, без сторонних плагинов | Требует навыков, возможна нагрузка при больших объемах | Выполнение пакетами и логирование |
| Плагины очистки каталога | Простота настройки, готовые решения | Могут быть избыточными, влияние на производительность | Использовать проверенные плагины с поддержкой |
| Ручное удаление через админку | Безопасно, минимальные риски | Трудоемко, не подходит для больших магазинов | Использовать вместе с автоматизацией |