Почему нужно автоматизировать удаление непроданных товаров в WooCommerce
В интернет-магазинах WooCommerce часто возникает задача очистки каталога от товаров, которые не были проданы за определенный период. Это помогает поддерживать актуальность ассортимента, улучшить производительность сайта и упростить управление товарами.
Ручное удаление занимает время и может привести к ошибкам. Автоматизация через WP-Cron позволяет регулярно запускать скрипт, который удаляет такие товары по заданным критериям.
Диагностика: как определить, что товары можно удалить
Перед автоматическим удалением нужно четко определить критерии:
- Товар не имеет ни одного заказа (не продан).
- Дата создания товара старше X дней (например, 90).
- Товар не находится в статусе "черновик" или "ожидание".
Для проверки можно выполнить SQL-запрос, чтобы найти количество таких товаров:
SELECT p.ID, p.post_date FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_name = p.post_title
WHERE p.post_type = 'product' AND p.post_status = 'publish'
GROUP BY p.ID
HAVING COUNT(oi.order_item_id) = 0 AND p.post_date < NOW() - INTERVAL 90 DAY;Если выборка содержит много записей, можно автоматизировать удаление.
Пошаговое решение: код для автоматического удаления товаров через WP-Cron
1. Регистрация cron-задания
add_action('wp', function() {
if (!wp_next_scheduled('wc_auto_delete_old_unsold_products')) {
wp_schedule_event(time(), 'daily', 'wc_auto_delete_old_unsold_products');
}
});2. Обработчик cron задачи
add_action('wc_auto_delete_old_unsold_products', function() {
global $wpdb;
// Период в днях для удаления
$days = 90;
// Получаем ID товаров, которые не проданы и старше $days дней
$query = $wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN (
SELECT DISTINCT order_item_meta.post_id
FROM {$wpdb->prefix}woocommerce_order_items oi
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON oi.order_item_id = order_item_meta.order_item_id
WHERE order_item_meta.meta_key = '_product_id'
) sold ON sold.post_id = p.ID
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND sold.post_id IS NULL
AND p.post_date < NOW() - INTERVAL %d DAY",
$days
);
$product_ids = $wpdb->get_col($query);
if (empty($product_ids)) {
return; // Нет товаров для удаления
}
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true); // Безопасное удаление с обходом корзины
}
});3. Очистка cron при деактивации темы или плагина
register_deactivation_hook(__FILE__, function() {
$timestamp = wp_next_scheduled('wc_auto_delete_old_unsold_products');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wc_auto_delete_old_unsold_products');
}
});Как проверить, что автоматическое удаление работает
- Включите WP_DEBUG в
wp-config.phpи добавьте логирование в обработчик для проверки ID удаляемых товаров. - Запустите вручную cron-задачу через плагин WP Crontrol или вызовите обработчик через
do_action('wc_auto_delete_old_unsold_products');. - Проверьте в админке WooCommerce, что товары, удовлетворяющие условию, исчезли.
- Убедитесь, что в отчетах заказов отсутствуют удалённые товары.
Частые ошибки и их исправление
- Неверный выборка товаров: учитывайте использование кастомных полей и вариаций. Наш запрос основывается на метаполях заказов и может не учитывать вариации, если мета ключ другой.
- Удаление активных товаров: проверьте, что статус товаров —
publish, чтобы не удалять черновики или архивные товары. - WP-Cron не запускается: стандартный WP-Cron зависит от посещений сайта. Для стабильности настройте системный cron на вызов
wp-cron.php. - Ошибка при удалении товаров: убедитесь, что у пользователя, под которым выполняется код, есть права на удаление постов.
Практические рекомендации по безопасности и производительности
- Запускайте удаление не чаще раза в сутки, чтобы не нагружать сервер.
- Проверяйте наличие резервных копий перед автоматическим удалением.
- При большом количестве товаров делайте удаление пакетами (порциями по 50-100), чтобы избежать таймаутов.
- Логируйте операции в отдельный файл или таблицу для аудита.
- Для ускорения используйте прямые SQL-запросы выборки, но удаление делайте через
wp_delete_post(), чтобы корректно очистить все связанные данные.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
| Плагин очистки (например, WP Sweep) | Удобство, опции настроек, UI | Может не поддерживать конкретные задачи под WooCommerce |
| Кастомный код с WP-Cron (как в статье) | Точный контроль, адаптация под задачи | Требует навыков, возможны ошибки в коде |
| Ручное удаление через админку | Простота для новичков | Ручной труд, риск пропуска |