Диагностика проблемы: почему важно отключать неактивные товары
В больших интернет-магазинах на WooCommerce со временем накапливаются товары, которые не продаются длительное время. Это ведёт к увеличению нагрузки на базу данных, снижению релевантности каталога и ухудшению пользовательского опыта. Автоматическое отключение таких товаров помогает сохранить актуальность ассортимента и повысить производительность сайта.
Как определить товары без продаж за нужный период
Для этого нужно получить список товаров, у которых отсутствуют заказы за последние N дней. WooCommerce хранит заказы в таблице wp_posts с типом shop_order, а позиции товаров — в wp_woocommerce_order_items и wp_woocommerce_order_itemmeta. Для ускорения решения используем WP_Query с мета-запросом и SQL-запросы для проверки продаж.
Пример SQL-запроса для поиска товаров без продаж за 90 дней
SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN (
SELECT DISTINCT im.meta_value AS product_id FROM wp_woocommerce_order_items oi
JOIN wp_woocommerce_order_itemmeta im ON oi.order_item_id = im.order_item_id
JOIN wp_posts o ON o.ID = oi.order_id
WHERE im.meta_key = '_product_id'
AND o.post_type = 'shop_order'
AND o.post_status IN ('wc-completed', 'wc-processing')
AND o.post_date >= DATE_SUB(NOW(), INTERVAL 90 DAY)
) sold_products ON p.ID = sold_products.product_id
WHERE p.post_type = 'product'
AND sold_products.product_id IS NULL
AND p.post_status = 'publish';Этот запрос выбирает опубликованные товары, у которых нет заказов со статусами wc-completed или wc-processing за последние 90 дней.
Пошаговое решение: как автоматически отключать товары без продаж
Реализуем решение через WP-Cron, чтобы периодически запускать проверку и менять статус товара на draft (черновик) для отключения с фронта.
Шаг 1. Создайте функцию для получения ID неактивных товаров
function get_inactive_products($days = 90) {
global $wpdb;
$query = $wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN (
SELECT DISTINCT im.meta_value AS product_id FROM {$wpdb->prefix}woocommerce_order_items oi
JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON oi.order_item_id = im.order_item_id
JOIN {$wpdb->posts} o ON o.ID = oi.order_id
WHERE im.meta_key = '_product_id'
AND o.post_type = 'shop_order'
AND o.post_status IN ('wc-completed', 'wc-processing')
AND o.post_date >= DATE_SUB(NOW(), INTERVAL %d DAY)
) sold_products ON p.ID = sold_products.product_id
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND sold_products.product_id IS NULL",
$days
);
return $wpdb->get_col($query);
}Шаг 2. Создайте функцию для смены статуса товаров
function disable_inactive_products($days = 90) {
$inactive_products = get_inactive_products($days);
foreach ($inactive_products as $product_id) {
wp_update_post([
'ID' => $product_id,
'post_status' => 'draft'
]);
}
}Шаг 3. Настройте WP-Cron для регулярного выполнения
Добавьте в файл functions.php или в плагин следующий код:
if (!wp_next_scheduled('disable_inactive_products_daily')) {
wp_schedule_event(time(), 'daily', 'disable_inactive_products_daily');
}
add_action('disable_inactive_products_daily', function() {
disable_inactive_products(90); // Период в днях
});Проверка результата после внедрения
- Запустите функцию вручную из консоли WP-CLI:
wp eval 'disable_inactive_products(90);' - Проверьте в административной панели, что товары без продаж за 90 дней получили статус
Черновик. - Проверьте базу данных таблицу
wp_posts, убедитесь, что у нужных товаров в полеpost_statusстоитdraft. - Проверьте на фронтенде сайта, что отключённые товары не отображаются в каталоге.
Частые ошибки и как их исправить
- Ошибка: WP-Cron не запускается регулярно.
Причина: На сайте низкий трафик или отключён системный cron.
Решение: Настройте системный cron для запуска WP-Cron или используйте плагин для управления cron. - Ошибка: Товары не меняют статус.
Причина: Неверные права пользователя или конфликт с плагинами.
Решение: Проверьте права пользователя, отключите конфликтующие плагины, проверьте логи ошибок. - Ошибка: Запрос работает медленно на больших базах.
Причина: Отсутствие индексов или слишком сложный SQL.
Решение: Оптимизируйте базу, добавьте индексы на поляpost_type,post_status, используйте WP-CLI для пакетной обработки.
Практические советы по оптимизации и безопасности
- Перед массовым обновлением сделайте резервную копию базы данных.
- Ограничьте количество товаров, обрабатываемых за один запуск, чтобы избежать таймаутов (например, обрабатывать по 50 товаров за раз).
- Используйте транзакции или батчи, если планируете расширять логику отключения.
- Добавьте логирование действий в отдельный файл или таблицу для контроля изменений.
- Регулярно проверяйте и удаляйте устаревшие записи черновиков, чтобы не засорять базу.
Сравнение вариантов реализации автоматического отключения товаров
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| WP-Cron + SQL-запрос | Регулярный запуск кастомного SQL-запроса с обновлением статусов | Гибкость, не требует плагинов, можно кастомизировать | Нагрузка на базу, сложность настройки, зависит от WP-Cron |
| Плагин автоматизации (например, WP All Import + фильтры) | Использование готовых плагинов для управления товарами | Простота настройки, поддержка, визуальный интерфейс | Зависимость от стороннего ПО, возможные лицензии |
| Ручное отключение через админку | Отслеживание и отключение товаров вручную | Полный контроль, нет кода | Трудозатратно, неэффективно для больших каталогов |