Диагностика проблемы: зачем удалять товары без остатков и заказов
В больших интернет-магазинах на WooCommerce часто накапливаются товары, которые больше не продаются, у которых нулевой остаток и отсутствуют заказы. Такие товары засоряют базу данных, замедляют админку и усложняют управление каталогом. Автоматическое удаление таких позиций позволяет поддерживать магазин в чистоте без лишних затрат времени.
Как определить товары для удаления
Для начала нужно четко определить, какие товары подлежат удалению. Обычно это:
- Товары с остатком 0 или меньше (stock quantity <= 0)
- Товары, по которым не было заказов (нет записей в таблице
wp_woocommerce_order_items) - При необходимости — товары, которые не продаются длительное время (по дате последнего заказа)
Пример SQL-запроса для выборки товаров без заказов:
SELECT p.ID FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON p.ID = oi.order_item_id
WHERE p.post_type = 'product' AND oi.order_item_id IS NULL;Однако лучше использовать WP_Query и WooCommerce API, чтобы избежать проблем с кешем и совместимостью.
Пошаговое решение: автоматическое удаление через wp_cron и PHP
1. Создаем функцию для проверки и удаления товаров
function wc_delete_products_without_stock_and_orders() {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => '_stock',
'value' => 0,
'compare' => '<=',
'type' => 'NUMERIC'
]
],
'fields' => 'ids'
];
$products = get_posts($args);
foreach ($products as $product_id) {
$orders = wc_get_orders([
'limit' => 1,
'status' => 'any',
'meta_key' => '_product_id',
'meta_value' => $product_id,
]);
if (empty($orders)) {
wp_delete_post($product_id, true); // без перемещения в корзину
}
}
}Обратите внимание: wc_get_orders по умолчанию не ищет по мета ключам товаров, поэтому такой метод может не работать. Вместо этого нужно проверить наличие заказов через запрос к таблицам базы.
2. Корректная проверка заказов через запрос к базе
global $wpdb;
function wc_product_has_orders($product_id) {
$query = $wpdb->prepare(
"SELECT COUNT(oi.order_item_id) FROM {$wpdb->prefix}woocommerce_order_items oi
JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
JOIN {$wpdb->prefix}posts p ON p.ID = oi.order_id
WHERE oim.meta_key = '_product_id' AND oim.meta_value = %d AND p.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold')",
$product_id
);
$count = $wpdb->get_var($query);
return $count > 0;
}3. Интеграция с wp_cron для периодического запуска
function wc_schedule_product_cleanup() {
if (!wp_next_scheduled('wc_cleanup_products_event')) {
wp_schedule_event(time(), 'daily', 'wc_cleanup_products_event');
}
}
add_action('wp', 'wc_schedule_product_cleanup');
add_action('wc_cleanup_products_event', 'wc_delete_products_without_stock_and_orders');Проверка результата после внедрения
После настройки крона и функции очистки проверьте:
- В админке WooCommerce исчезают товары с нулевым остатком и без заказов
- В базе данных (таблица
wp_posts) не осталось таких товаров - Журнал ошибок PHP не содержит предупреждений от вашей функции
- Крон срабатывает (можно использовать плагин WP Crontrol для управления задачами)
Частые ошибки и как их исправить
- Неверная проверка заказов: Использование
wc_get_ordersс параметрами по мета-ключу товара не работает. Решение — использовать SQL-запрос к таблицам WooCommerce, как показано выше. - Потеря данных: удаление товаров без резервного копирования. Рекомендуется перед автоматическим удалением делать бэкап базы.
- Крон не срабатывает: wp_cron зависит от посещений сайта. Для надежной работы настройте системный cron на вызов wp-cron.php или используйте плагин WP Crontrol.
- Удаление товаров с продажами: из-за ошибки в запросах или логике могут удаляться нужные товары. Проверьте логи и отладьте функцию на тестовом сайте.
Практические советы по безопасности и производительности
- Ограничьте количество удаляемых товаров за один запуск, чтобы не перегружать сервер. Добавьте параметр
'posts_per_page' => 50и вызывайте функцию несколько раз с задержкой. - Используйте проверки прав пользователя, если запускаете функцию вручную или из админки.
- Логируйте результаты удаления с указанием ID товаров и времени.
- Резервируйте базу данных перед массовыми удалениями.
Сравнение вариантов реализации очистки товаров
| Вариант | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| Использование wp_cron + SQL запрос | Высокая точность проверки заказов; гибкость | Сложность написания запроса; требует понимания базы данных | Использовать готовые запросы из документации WooCommerce |
| Использование wc_get_orders | Простота кода, использование API WooCommerce | Не позволяет эффективно фильтровать по товарам; медленная работа на больших магазинах | Использовать для выборки заказов по другим признакам, а не для поиска товаров |
| Плагины очистки | Готовые решения с интерфейсом | Могут не иметь нужной логики удаления; дополнительная нагрузка | Использовать для ручной очистки, а не для автоматизации |