Диагностика проблемы: зачем удалять товары без заказов
В WooCommerce накапливаются товары, которые не покупаются, что приводит к загромождению каталога, снижению производительности и ухудшению пользовательского опыта. Автоматическое удаление таких товаров помогает поддерживать актуальность ассортимента и уменьшить нагрузку на базу данных.
Пошаговое решение: скрипт для удаления товаров без заказов
1. Определение товаров без заказов
Для начала нужно получить список товаров, у которых нет связанных заказов. Для этого используем SQL-запрос или WP_Query с условием на наличие заказов.
2. Создание функции удаления
Добавим функцию, которая удалит товары без заказов, используя стандартную функцию wp_delete_post().
function wc_delete_products_without_orders() {
global $wpdb;
// Получаем ID товаров, не входящих ни в один заказ
$product_ids = $wpdb->get_col(
"SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->prefix}woocommerce_order_items oi ON oi.order_item_name = p.ID
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND oim.meta_key = '_product_id'
AND oim.meta_value IS NULL"
);
if (empty($product_ids)) {
return 'Нет товаров без заказов';
}
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true); // Принудительно удаляем
}
return count($product_ids) . ' товаров удалено';
}3. Запуск функции по расписанию с помощью WP-Cron
Чтобы автоматизировать процесс, добавим задачу в WP-Cron, которая будет запускать функцию еженедельно.
function wc_schedule_delete_products_event() {
if (!wp_next_scheduled('wc_delete_products_event')) {
wp_schedule_event(time(), 'weekly', 'wc_delete_products_event');
}
}
add_action('wp', 'wc_schedule_delete_products_event');
add_action('wc_delete_products_event', 'wc_delete_products_without_orders');Проверка результата после внедрения
- Перейдите в раздел «Товары» в админке WooCommerce и проверьте, что товары без заказов удалены.
- Проверьте журнал событий WP-Cron через плагин WP Crontrol, чтобы убедиться, что задача запущена.
- Выполните функцию вручную через консоль WP-CLI для теста:
wp eval 'echo wc_delete_products_without_orders();'
Частые ошибки и способы их исправления
- Ошибка: Пустой список товаров для удаления
Причина: Некорректный SQL-запрос или не учитываются статусы заказов.
Решение: Проверьте запрос, убедитесь, что учитываются все статусы заказов, например, 'wc-completed', 'wc-processing'. - Ошибка: Функция не запускается по расписанию
Причина: WP-Cron отключен или неактивен.
Решение: Проверьте, что на сайте есть трафик, или настройте системный cron для вызова wp-cron.php. - Ошибка: Удаляются нужные товары
Причина: Логика определения товаров без заказов слишком грубая.
Решение: Добавьте дополнительные проверки, например, на дату создания товара или наличие атрибутов.
Практические советы по безопасности и производительности
- Перед удалением товаров сделайте резервную копию базы данных.
- Добавьте проверку времени создания товара, чтобы не удалять недавно добавленные товары (например, младше 30 дней).
- Для больших каталогов используйте пакетную обработку по 50-100 товаров за раз, чтобы избежать таймаутов.
- Для мониторинга создайте лог удалённых товаров, чтобы иметь возможность восстановить данные.
Пример улучшенной функции с проверкой даты и пакетной обработкой
function wc_delete_old_products_without_orders_batch($batch_size = 50) {
global $wpdb;
$date_threshold = date('Y-m-d H:i:s', strtotime('-30 days'));
$product_ids = $wpdb->get_col($wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND p.post_date < %s
AND NOT EXISTS (
SELECT 1 FROM {$wpdb->prefix}woocommerce_order_itemmeta oim
JOIN {$wpdb->prefix}woocommerce_order_items oi ON oim.order_item_id = oi.order_item_id
JOIN {$wpdb->prefix}posts o ON oi.order_id = o.ID
WHERE o.post_status IN ('wc-completed', 'wc-processing')
AND oim.meta_key = '_product_id'
AND oim.meta_value = p.ID
)
LIMIT %d",
$date_threshold,
$batch_size
));
if (empty($product_ids)) {
return 'Нет товаров для удаления в этом пакете';
}
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true);
}
return count($product_ids) . ' товаров удалено в этом пакете';
}Сравнение способов удаления товаров без заказов
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Полный SQL-запрос и удаление сразу | Быстрое удаление всех товаров | Риск таймаутов, нет контроля по времени | Маленький каталог, разовая чистка |
| Пакетная обработка с проверкой даты | Безопасно, контролируемо, можно запускать регулярно | Сложнее в реализации | Большие каталоги, регулярное обслуживание |
| Ручное удаление через админку | Простой контроль | Трудоемко, неавтоматично | Малое количество товаров, редко |