Диагностика проблемы: зачем удалять неактивные товары
В магазинах на WooCommerce со временем накапливаются товары, которые не обновлялись и не продавались долгое время. Они занимают место в базе данных, замедляют админку и снижают релевантность каталога. Часто владельцы не знают, как быстро и безопасно очистить такие товары.
Как определить неактивный товар
Для начала нужно понять, что считать «неактивным». Обычно это товары, которые не обновлялись или не имели заказов в течение определенного периода (например, 6 месяцев). Сравните даты post_modified и заказы в таблице wp_woocommerce_order_items.
Пошаговое решение: автоматическое удаление товаров старше N дней
Рассмотрим скрипт, который по крону удалит товары, не обновлявшиеся более 180 дней. Удалять будем товары с типом product и статусом publish.
function wpt_delete_old_products() {
$days = 180; // количество дней неактивности
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'date_query' => [
[
'column' => 'post_modified',
'before' => $date_threshold,
],
],
'posts_per_page' => -1,
'fields' => 'ids',
];
$query = new WP_Query($args);
if ($query->have_posts()) {
foreach ($query->posts as $product_id) {
wp_delete_post($product_id, true); // принудительно удаляем без корзины
}
}
}
// Регистрация ежесуточного события
if (!wp_next_scheduled('wpt_daily_delete_old_products')) {
wp_schedule_event(time(), 'daily', 'wpt_daily_delete_old_products');
}
add_action('wpt_daily_delete_old_products', 'wpt_delete_old_products');Этот код можно добавить в файл functions.php вашей темы или в отдельный плагин.
Как учесть заказы и продажи
Удалять товары, которые продаются, нежелательно. Для этого нужно исключить товары, которые были в заказах за последние N дней.
function wpt_get_sold_products_last_days($days) {
global $wpdb;
$date_after = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$query = $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 orders.post_type = 'shop_order'
AND orders.post_status IN ('wc-completed','wc-processing')
AND orders.post_date > %s
AND order_item_meta.meta_key = '_product_id'",
$date_after
);
return $wpdb->get_col($query);
}
function wpt_delete_old_products_exclude_sold() {
$days = 180;
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$sold_products = wpt_get_sold_products_last_days($days);
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'date_query' => [
[
'column' => 'post_modified',
'before' => $date_threshold,
],
],
'posts_per_page' => -1,
'fields' => 'ids',
'post__not_in' => $sold_products,
];
$query = new WP_Query($args);
if ($query->have_posts()) {
foreach ($query->posts as $product_id) {
wp_delete_post($product_id, true);
}
}
}
if (!wp_next_scheduled('wpt_daily_delete_old_products')) {
wp_schedule_event(time(), 'daily', 'wpt_daily_delete_old_products');
}
add_action('wpt_daily_delete_old_products', 'wpt_delete_old_products_exclude_sold');Проверка результата после внедрения
- В админке WooCommerce проверьте количество товаров до и после запуска скрипта.
- Для ручного теста вызовите функцию через
do_action('wpt_daily_delete_old_products')в консоли WP-CLI или добавьте временный вызов в код. - Проверьте логи ошибок, чтобы убедиться, что нет фатальных ошибок.
- Просмотрите базу данных через phpMyAdmin или WP CLI, чтобы убедиться, что старые товары удалены.
Частые ошибки и как исправить
- Удаляются активные товары: проверьте условия исключения товаров с продажами и, если нужно, расширьте исключения по меткам или категориям.
- Скрипт не запускается: убедитесь, что wp-cron работает, или настройте системный CRON для вызова
wp-cron.php. - Удаление занимает слишком много времени: используйте постраничный запрос (например, по 50 товаров за раз) и запускайте удаление в несколько шагов.
- Потеря данных: всегда делайте резервную копию перед массовым удалением.
Практические советы по безопасности и производительности
- Добавьте логирование: записывайте ID удаляемых товаров в отдельный файл, чтобы при необходимости восстановить информацию.
- Используйте транзакции базы данных, если планируете более сложные операции.
- Для больших магазинов лучше разделить скрипт на несколько частей с пагинацией.
- Не удаляйте товары навсегда сразу — сначала переводите их в статус черновика (
draft) и проверяйте результаты.
Сравнение подходов: плагин vs кастомный код
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Готовый плагин очистки | Простота установки, UI для настройки | Может удалять не то, что нужно; нагрузка; ограниченная кастомизация | Используйте с фильтрами и тестированием |
| Кастомный код (пример из статьи) | Точная настройка; минимальная нагрузка; можно интегрировать в процессы | Требует навыков PHP и тестирования | Оптимален для опытных разработчиков |