Диагностика проблемы: зачем удалять товары по устаревшим заказам
В WooCommerce часто возникает задача очистки каталога от товаров, связанных с устаревшими или отменёнными заказами. Это актуально для магазинов с ограниченным ассортиментом или с товарами, которые зависят от наличия на складе. Без регулярной очистки база данных разрастается, что замедляет работу сайта и усложняет управление товарами.
Проверьте, есть ли в вашем магазине товары, которые не продаются долгое время или связаны с заказами со статусом, например, "отменён" или "возврат". Для этого можно воспользоваться SQL-запросом:
SELECT p.ID, p.post_title, MAX(o.post_date) AS last_order_date
FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_name = p.post_title
LEFT JOIN wp_posts o ON oi.order_id = o.ID AND o.post_type = 'shop_order'
WHERE p.post_type = 'product'
GROUP BY p.ID
HAVING last_order_date < DATE_SUB(NOW(), INTERVAL 6 MONTH) OR last_order_date IS NULL;Этот запрос покажет товары, для которых последнее связанное с ними заказы были сделаны более 6 месяцев назад или отсутствуют вовсе.
Пошаговое решение: автоматическое удаление товаров по устаревшим заказам
1. Создаём функцию для выборки товаров с устаревшими заказами
Добавьте следующий код в файл functions.php вашей темы или в отдельный плагин:
function get_products_by_old_orders( $months = 6 ) {
global $wpdb;
$query = $wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->prefix}woocommerce_order_items oi ON oi.order_item_name = p.post_title
LEFT JOIN {$wpdb->posts} o ON oi.order_id = o.ID AND o.post_type = 'shop_order'
WHERE p.post_type = 'product'
GROUP BY p.ID
HAVING MAX(o.post_date) < DATE_SUB(NOW(), INTERVAL %d MONTH) OR MAX(o.post_date) IS NULL",
$months
);
return $wpdb->get_col( $query );
}2. Функция удаления товаров по ID
function delete_products_by_ids( $product_ids ) {
foreach ( $product_ids as $product_id ) {
wp_delete_post( $product_id, true ); // true - удаление без возможности восстановления
}
}3. Настройка WP-Cron для регулярного удаления
Создайте задачу для автоматического запуска очистки раз в месяц:
if ( ! wp_next_scheduled( 'auto_delete_old_products_hook' ) ) {
wp_schedule_event( time(), 'monthly', 'auto_delete_old_products_hook' );
}
add_action( 'auto_delete_old_products_hook', function() {
$old_products = get_products_by_old_orders( 6 ); // товары без заказов 6 месяцев
if ( ! empty( $old_products ) ) {
delete_products_by_ids( $old_products );
}
});Проверка результата после внедрения
Для проверки выполните следующие шаги:
- Вручную вызовите функцию и выведите список ID товаров, которые будут удалены:
$products = get_products_by_old_orders(6); print_r($products); - Проверьте панель управления WooCommerce — соответствующие товары должны исчезнуть.
- Для теста запустите вручную событие WP-Cron с помощью плагина WP Crontrol или вызовите функцию напрямую.
Частые ошибки и как исправить
- Ошибка: Пустой результат выборки товаров.
Причина: Неправильно настроена дата или отсутствуют корректные связи между заказами и товарами.
Решение: Проверьте структуру таблицwoocommerce_order_itemsи убедитесь, чтоorder_item_nameсовпадает сpost_titleтовара. Лучше заменить JOIN наorder_item_idс мета-данными. - Ошибка: Товары не удаляются.
Причина: Отсутствие прав на удаление или отключена функцияwp_delete_post.
Решение: Проверьте, что код выполняется с правами администратора и что нет плагинов, блокирующих удаление. - Ошибка: Удаляются нужные товары.
Причина: Слишком широкие условия выборки.
Решение: Уточните критерии, добавьте проверки по статусу заказа (например, исключить "завершённые")
Практические советы по безопасности и производительности
- Перед массовым удалением сделайте резервную копию базы данных.
- Добавьте логирование удалённых товаров для аудита.
- Оптимизируйте SQL-запрос, используя мета-данные
woocommerce_order_itemmetaдля точной связи товаров и заказов. - Используйте транзакции или периодическую обработку пакетами, чтобы избежать таймаутов.
Сравнение способов реализации автоматического удаления товаров
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| SQL + WP-Cron | Прямой запрос к базе с регулярным запуском | Быстро, не требует плагинов | Сложность корректной настройки, риск ошибок в запросах |
| Плагин очистки | Использование готового решения, например WP Sweep | Простота, безопасность | Могут быть избыточными, не всегда гибкие |
| Ручное удаление | Через админку или экспорт | Полный контроль | Трудоёмко, не автоматизировано |