Проблема: как автоматически удалять товары без заказов в WooCommerce
Интернет-магазины на WooCommerce часто сталкиваются с ситуацией, когда в каталоге остаются товары, которые так и не были куплены. Это может мешать удобству управления магазином, усложнять навигацию для пользователей и создавать нагрузку на базу данных. Автоматическое удаление таких товаров по прошествии заданного времени с момента публикации или последнего заказа помогает поддерживать каталог в актуальном состоянии.
Диагностика: как определить товары без заказов
Для реализации удаления необходимо аккуратно выявить товары, которые не имеют связанных заказов. В WooCommerce связь товаров и заказов хранится в таблицах базы данных: wp_posts для товаров (post_type = 'product') и wp_posts для заказов (post_type = 'shop_order'). Связь между заказом и товаром хранится в wp_woocommerce_order_items и wp_woocommerce_order_itemmeta.
Проверить, есть ли заказы с конкретным ID товара, можно через SQL-запрос, но в коде WordPress проще использовать WC API и WP_Query.
Пошаговое решение: пример кода для автоматического удаления
1. Создаем WP-Cron задачу для еженедельной проверки
if (!wp_next_scheduled('wptem_delete_unsold_products')) {
wp_schedule_event(time(), 'weekly', 'wptem_delete_unsold_products');
}2. Функция для удаления товаров без заказов за X дней
function wptem_delete_unsold_products_callback() {
$days_threshold = 90; // Количество дней с момента публикации
$date_threshold = date('Y-m-d H:i:s', strtotime('-' . $days_threshold . ' days'));
// Получаем товары, опубликованные до пороговой даты
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'date_query' => [
[
'before' => $date_threshold,
'inclusive' => true,
],
],
'post_status' => 'publish',
'fields' => 'ids',
];
$products = get_posts($args);
foreach ($products as $product_id) {
// Проверяем есть ли заказы с этим товаром
if (!wptem_product_has_orders($product_id)) {
wp_delete_post($product_id, true); // Полное удаление
}
}
}
add_action('wptem_delete_unsold_products', 'wptem_delete_unsold_products_callback');
function wptem_product_has_orders($product_id) {
global $wpdb;
$query = $wpdb->prepare(
"SELECT COUNT(DISTINCT order_items.order_id) FROM {$wpdb->prefix}woocommerce_order_items AS order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON order_items.order_item_id = itemmeta.order_item_id
INNER JOIN {$wpdb->prefix}posts AS posts ON posts.ID = order_items.order_id
WHERE order_items.order_item_type = 'line_item'
AND itemmeta.meta_key = '_product_id'
AND itemmeta.meta_value = %d
AND posts.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold')",
$product_id
);
$count = $wpdb->get_var($query);
return $count > 0;
}3. Очистка WP-Cron при деактивации плагина/темы
function wptem_deactivate_cleanup() {
$timestamp = wp_next_scheduled('wptem_delete_unsold_products');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wptem_delete_unsold_products');
}
}
register_deactivation_hook(__FILE__, 'wptem_deactivate_cleanup');Как проверить, что удаление сработало
- В админке WooCommerce сравните количество товаров до и после запуска крона.
- Запустите функцию вручную (через WP-CLI или временно добавьте вызов
wptem_delete_unsold_products_callback();в functions.php) и проверьте логи ошибок. - Проверьте, что удалены только товары без заказов, опубликованные более 90 дней назад.
Частые ошибки и как их исправить
- Удаляются товары с заказами: проверьте логику функции
wptem_product_has_orders()и правильность статусов заказов в SQL-запросе. - Крон не срабатывает: убедитесь, что WP-Cron включен и посещения сайта есть. Для теста используйте WP-CLI:
wp cron event run wptem_delete_unsold_products. - Превышение лимитов памяти или таймауты: разбейте удаление на партии по 50-100 товаров за запуск, добавив параметр
posts_per_pageи пагинацию.
Практические советы по безопасности и производительности
- Запускайте удаление товаров только по расписанию, а не на каждом запросе.
- Делайте резервные копии базы перед автоматическим удалением.
- Добавьте логирование удалений в отдельный файл или таблицу для аудита.
- Для больших магазинов с тысячами товаров используйте пагинацию и оптимизируйте SQL-запросы.
Сравнение вариантов реализации удаления товаров
| Метод | Плюсы | Минусы |
|---|---|---|
| WP-Cron с кастомным кодом | Гибкость, кастомизация, без сторонних плагинов | Требует знаний, настройка cron, возможны таймауты при большом объеме |
| Плагины очистки WooCommerce | Простота настройки, готовые решения | Могут быть избыточными, нагрузка, нет тонкой настройки |
| Ручное удаление через SQL или админку | Контроль и точечное удаление | Риск ошибок, неавтоматизировано, трудозатратно |