Диагностика проблемы: почему нужно удалять товары без заказов
В магазинах на WooCommerce с большим ассортиментом часто накапливаются товары, которые не продаются и не привлекают клиентов. Это усложняет управление каталогом, увеличивает размер базы данных и может замедлять работу сайта. Чтобы поддерживать актуальность каталога, полезно регулярно удалять такие товары, которые не получили заказов за определённый период.
Как определить товары без заказов за период
Для начала необходимо получить список товаров, которые не были куплены за заданное количество дней. В WooCommerce заказы и товары связаны через таблицы wp_woocommerce_order_items и wp_woocommerce_order_itemmeta. Однако для упрощения задачи можно использовать WP_Query с мета-запросами и дополнительную логику на PHP.
Пример запроса для получения ID товаров без заказов за 30 дней
function get_products_without_orders( $days = 30 ) {
global $wpdb;
$date_threshold = date( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) );
// Получаем ID товаров, которые были в заказах за последние $days дней
$ordered_product_ids = $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 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 >= %s",
$date_threshold
));
if ( empty( $ordered_product_ids ) ) {
// Если заказов не было, возвращаем все товары
$all_products = get_posts( [
'post_type' => 'product',
'numberposts' => -1,
'fields' => 'ids',
] );
return $all_products;
}
// Получаем все товары
$all_products = get_posts( [
'post_type' => 'product',
'numberposts' => -1,
'fields' => 'ids',
] );
// Вычитаем товары с заказами
return array_diff( $all_products, $ordered_product_ids );
}Пошаговое решение: автоматизация удаления товаров
Чтобы автоматизировать процесс, создадим WP-Cron задачу, которая будет запускаться например раз в сутки, находить такие товары и удалять их.
1. Функция удаления товаров без заказов
function delete_products_without_orders_cron() {
$days = 30; // Период без заказов
$products_to_delete = get_products_without_orders( $days );
if ( empty( $products_to_delete ) ) {
return;
}
foreach ( $products_to_delete as $product_id ) {
wp_delete_post( $product_id, true ); // Полное удаление
}
}2. Регистрация WP-Cron задачи
add_action( 'wpengine_daily_delete_products', 'delete_products_without_orders_cron' );
function wpengine_schedule_delete_products_event() {
if ( ! wp_next_scheduled( 'wpengine_daily_delete_products' ) ) {
wp_schedule_event( time(), 'daily', 'wpengine_daily_delete_products' );
}
}
add_action( 'wp', 'wpengine_schedule_delete_products_event' );3. Как вручную запустить задачу (для тестирования)
// Временно вызовем функцию для проверки
add_action( 'admin_init', function() {
if ( isset( $_GET['run_delete_products'] ) && current_user_can( 'manage_options' ) ) {
delete_products_without_orders_cron();
wp_die( 'Удаление товаров выполнено' );
}
});Проверка результата после внедрения
- Перейдите в раздел Товары в админке и проверьте, что товары без заказов за последний месяц удалены.
- Запустите вручную удаление по ссылке
https://example.com/wp-admin/?run_delete_products=1под своей учетной записью с правами администратора. - Проверьте логи сервера и отладочные логи WordPress на предмет ошибок.
- Убедитесь, что WP-Cron событие
wpengine_daily_delete_productsзапланировано (например через плагин WP Crontrol).
Частые ошибки и как исправить
- WP-Cron не запускается: По умолчанию WP-Cron активируется при посещении сайта. Если трафика мало, cron может не срабатывать. Решение: настроить системный cron на сервере для вызова
wp-cron.phpили использовать плагины для управления задачами. - Удаление не происходит: Проверьте, что функция
get_products_without_orders()корректно возвращает ID товаров. Ошибка в SQL-запросе или права доступа к базе могут блокировать получение данных. - Удаляются нужные товары: Убедитесь, что фильтрация по датам и статусам заказов настроена правильно. Перед удалением полезно выводить список товаров для проверки.
- Высокая нагрузка при выполнении: Если товаров слишком много, удаление всех за один раз может вызвать таймаут. Разбейте удаление на партии по 50-100 товаров.
Практические советы по производительности и безопасности
- Перед автоматическим удалением товаров делайте резервную копию базы данных.
- Добавьте логирование действий удаления в отдельный файл или в системный лог для аудита.
- Для больших магазинов используйте пакетную обработку (batch processing) с transients или options для сохранения прогресса.
- Используйте проверки nonce и права пользователя, если делаете ручной запуск через URL.
- Если не хотите полностью удалять товары, можно сначала переводить их в черновики с помощью
wp_update_post(['ID' => $product_id, 'post_status' => 'draft']).
Сравнение способов реализации автоматического удаления товаров
| Метод | Преимущества | Недостатки |
|---|---|---|
| WP-Cron с кастомной функцией | Гибкость, полный контроль, не требует сторонних плагинов | Зависит от трафика, требует отладки SQL и PHP-кода |
| Плагины для автоматизации очистки каталога | Простота настройки, готовые интерфейсы | Могут быть тяжелыми, не всегда гибкие под задачи |
| Ручное удаление через админку | Безопасность, контроль | Трудоемко, неэффективно для больших магазинов |