Диагностика задачи: зачем отключать неактивные товары
В интернет-магазинах на WooCommerce с большим каталогом часто появляется проблема с товарами, которые долго не продаются. Такие товары занимают место в каталоге, негативно влияют на SEO и пользовательский опыт, а также могут создавать нагрузку на базу данных. Автоматическое отключение таких товаров позволяет эффективно поддерживать ассортимент в актуальном состоянии без ручного контроля.
Как определить товары без продаж за период
Для решения задачи нужно получить список товаров, у которых не было заказов за последний N дней. WooCommerce хранит данные о заказах и позициях заказов в таблицах wp_posts (тип записи – shop_order) и wp_woocommerce_order_items с метаданными в wp_woocommerce_order_itemmeta.
На практике проще использовать WP_Query с фильтрацией по метаданным или прямые SQL-запросы. Ниже пример SQL-запроса для получения ID товаров без продаж за последние 90 дней:
SELECT p.ID FROM wp_posts p
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND p.ID NOT IN (
SELECT DISTINCT order_item_meta.meta_value
FROM wp_woocommerce_order_items order_items
INNER JOIN wp_woocommerce_order_itemmeta order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
INNER JOIN wp_posts orders ON orders.ID = order_items.order_id
WHERE order_item_meta.meta_key = '_product_id'
AND orders.post_type = 'shop_order'
AND orders.post_status IN ('wc-completed', 'wc-processing')
AND orders.post_date >= DATE_SUB(NOW(), INTERVAL 90 DAY)
);
Этот запрос возвращает ID товаров, которые не продавались за последние 90 дней и сейчас опубликованы.
Пошаговое решение: отключаем неактивные товары программно
Реализуем задачу через WP-Cron, который ежесуточно проверяет и переводит неактивные товары в статус draft (отключает публикацию). Пример кода для файла functions.php или собственного плагина:
function disable_inactive_products() {
global $wpdb;
$days = 90; // Период без продаж
$query = $wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
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_type = 'shop_order'
AND orders.post_status IN ('wc-completed', 'wc-processing')
AND orders.post_date >= DATE_SUB(NOW(), INTERVAL %d DAY)
)",
$days
);
$product_ids = $wpdb->get_col($query);
if (!empty($product_ids)) {
foreach ($product_ids as $product_id) {
// Обновляем статус товара на draft
wp_update_post(array(
'ID' => $product_id,
'post_status' => 'draft'
));
}
}
}
// Регистрируем ежедневное событие при активации темы или плагина
if (!wp_next_scheduled('disable_inactive_products_daily')) {
wp_schedule_event(time(), 'daily', 'disable_inactive_products_daily');
}
// Привязываем функцию к событию
add_action('disable_inactive_products_daily', 'disable_inactive_products');
Этот код добавляет ежедневную задачу, которая отключает все товары без продаж за последние 90 дней.
Как проверить, что решение сработало
- Через админ-панель перейдите в Товары и отфильтруйте по статусу
Черновик. Там должны появиться отключённые товары. - В базе данных в таблице
wp_postsу товаров изменится полеpost_statusнаdraft. - Для отладки можно временно добавить логирование в функцию для вывода отключённых ID.
Частые ошибки и как их исправить
- Отсутствие заказов с нужными статусами: если в магазине используются нестандартные статусы заказов, их нужно добавить в условие
post_status IN ('wc-completed', 'wc-processing'). - Проблемы с WP-Cron: если задачи не выполняются, убедитесь, что на сайте есть посещения или настройте системный cron для вызова
wp-cron.php. - Неправильные префиксы таблиц: используйте
$wpdb->prefix, а не жестко прописанныйwp_. - Потеря товаров из-за неправильного периода: не ставьте слишком короткий период, чтобы не отключить активные товары.
Практические советы по безопасности и производительности
- Для больших каталогов запрос может быть тяжёлым. В таком случае разбивайте обработку на чанки, например, по 100 товаров.
- Добавьте проверку прав пользователя, если функцию вызываете из интерфейса.
- Перед массовым изменением статусов сделайте резервную копию базы данных.
- Для высокой нагрузки используйте WP-CLI скрипт, который можно запускать из командной строки по расписанию, исключая ограничения веб-сервера.
- Если хотите уведомлять админа, добавьте отправку email с отчётом о деактивированных товарах.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
| WP-Cron + SQL запрос | Гибко, автоматично, не требует плагинов | Зависит от посещаемости сайта, сложность запросов при большом каталоге |
| Плагин автоматизации | Простота настройки, интерфейс, поддержка | Дополнительные ресурсы, возможные конфликты, лицензии |
| WP-CLI скрипт | Высокая производительность, удобство при больших объемах | Требует доступа к серверу и навыков командной строки |