Диагностика проблемы: зачем автоматически отключать товары в WooCommerce
Интернет-магазины с большим каталогом товаров сталкиваются с проблемой «зависших» товаров — тех, которые не продаются длительное время. Они занимают место в каталоге, ухудшают пользовательский опыт и могут влиять на SEO. Ручное отключение таких товаров — трудоёмкий процесс. Автоматизация решения этой задачи помогает поддерживать актуальность ассортимента и улучшать конверсию.
Как определить товары без продаж за период
Для начала нужно получить список товаров, которые не имели продаж за заданный промежуток времени. В WooCommerce данные о заказах хранятся в таблицах wp_posts (заказы) и wp_woocommerce_order_items (товары в заказах). Чтобы получить товары без продаж, нужно:
- Выбрать все товары (продукты) из
wp_postsс типомproduct. - Получить список товаров, которые были в заказах со статусом
wc-completedилиwc-processingза период. - Отфильтровать товары, которые не встречаются в заказах за этот период.
Для примера можно использовать WP_Query и SQL-запросы, но проще оперировать через PHP и WooCommerce API.
Пошаговое решение с примером кода
1. Создаём функцию для получения ID товаров без продаж
function get_products_without_sales( $days = 30 ) {
global $wpdb;
$date_from = date('Y-m-d H:i:s', strtotime("-" . intval($days) . " days"));
// Получаем ID товаров, проданных за период
$sold_products = $wpdb->get_col( $wpdb->prepare(
"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->prefix}posts AS posts ON order_items.order_id = posts.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 >= %s
", $date_from
) );
if ( empty( $sold_products ) ) {
// Если продаж не было, возвращаем всех опубликованных товаров
$all_products = get_posts( [
'post_type' => 'product',
'posts_per_page' => -1,
'fields' => 'ids',
'post_status' => 'publish',
] );
return $all_products;
}
// Получаем все опубликованные товары
$all_products = get_posts( [
'post_type' => 'product',
'posts_per_page' => -1,
'fields' => 'ids',
'post_status' => 'publish',
] );
// Возвращаем товары, которых нет в списке проданных
return array_diff( $all_products, $sold_products );
}
2. Создаём функцию для автоматического отключения товаров
function disable_unsold_products( $days = 30 ) {
$products_to_disable = get_products_without_sales( $days );
foreach ( $products_to_disable as $product_id ) {
// Меняем статус на 'draft' — товар будет снят с публикации
wp_update_post( [
'ID' => $product_id,
'post_status' => 'draft',
] );
}
}
3. Запускаем функцию через WP-Cron или вручную
Для автоматизации добавьте задачу в WP-Cron:
if ( ! wp_next_scheduled( 'auto_disable_unsold_products_daily' ) ) {
wp_schedule_event( time(), 'daily', 'auto_disable_unsold_products_daily' );
}
add_action( 'auto_disable_unsold_products_daily', function() {
disable_unsold_products( 30 ); // отключаем товары без продаж за 30 дней
} );
Или вызовите disable_unsold_products(30) вручную для проверки.
Проверка результата после внедрения
- Перейдите в админ-панель WooCommerce → Товары и отфильтруйте по статусу «Черновик». Должны появиться товары, которые не продавались последние 30 дней.
- Проверьте, что эти товары действительно не были проданы за период, сверив продажи.
- После повторного запуска через период товары без продаж должны автоматически становиться черновиками.
Частые ошибки и как исправить
- Ошибка: Функция не отключает товары.
Причина: Неправильный статус заказа для выборки или ошибки в запросе.
Решение: Проверьте, что учитываются статусыwc-completedиwc-processing. Используйте отладку SQL-запроса. - Ошибка: Отключаются товары с недавними продажами.
Причина: Неверно задан период или часовой пояс.
Решение: Убедитесь, что дата запроса корректна и соответствует часовому поясу сайта. - Ошибка: Задача WP-Cron не запускается.
Решение: Проверьте логи, настройте системный cron или используйте плагины для управления WP-Cron.
Практические советы по безопасности и производительности
- При массовом обновлении товаров лучше обрабатывать данные партиями, чтобы не перегружать сервер.
- Тестируйте код сначала на тестовой копии сайта, чтобы избежать случайного закрытия важных товаров.
- Периодично очищайте задачи WP-Cron, чтобы не создавать дубли и не перегружать систему.
- Используйте транзиенты или кэширование для уменьшения нагрузки на базу при частых вызовах.
Сравнение подходов: плагин vs собственный код
| Критерий | Плагин | Собственный код | Компромисс |
|---|---|---|---|
| Гибкость | Ограничена настройками | Полная, под свои нужды | Больше времени на разработку |
| Нагрузка | Может быть высокой из-за универсальности | Оптимизирован под задачу | Требует навыков оптимизации |
| Обновления | Автоматические | Необходим контроль | Можно автоматизировать через систему контроля версий |
| Безопасность | Зависит от разработчика плагина | Контролируете сами | Необходимо тестирование и аудит |