Диагностика проблемы: зачем и когда удалять товары без заказов
В интернет-магазинах на WooCommerce нередко появляется большое количество товаров, которые никто не покупал. Это увеличивает нагрузку на базу данных, затрудняет управление каталогом и ухудшает пользовательский опыт. Автоматическое удаление таких товаров поможет поддерживать актуальность ассортимента и улучшить производительность сайта.
Для начала важно понять, какие товары не имели заказов. Для этого можно использовать SQL-запрос или WP_Query с проверкой наличия связанных заказов.
Проверка наличия заказов у товара через SQL
SELECT p.ID, p.post_title FROM wp_posts p
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_name = p.post_title
LEFT JOIN wp_woocommerce_order_itemmeta oim ON oim.order_item_id = oi.order_item_id
WHERE p.post_type = 'product'
AND oim.meta_key = '_product_id'
AND oim.meta_value IS NULL;Этот запрос можно адаптировать для поиска товаров, не связанных с заказами.
Пошаговое решение: скрипт для удаления товаров без заказов
Используем WP_Query для получения товаров без заказов и удаляем их программно. Код рекомендуем запускать через WP-CLI или в отдельном плагине с безопасной активацией.
function wpc_remove_products_without_orders() {
// Получаем все товары
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'fields' => 'ids',
];
$products = get_posts($args);
foreach ($products as $product_id) {
global $wpdb;
// Проверяем наличие заказов с этим товаром
$has_orders = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_order_itemmeta om
INNER JOIN {$wpdb->prefix}woocommerce_order_items oi ON om.order_item_id = oi.order_item_id
INNER JOIN {$wpdb->prefix}posts p ON p.ID = oi.order_id
WHERE om.meta_key = '_product_id' AND om.meta_value = %d AND p.post_status IN ('wc-completed', 'wc-processing')",
$product_id
));
if (empty($has_orders)) {
// Удаляем товар без возможности восстановления (force delete)
wp_delete_post($product_id, true);
}
}
}
// Для запуска: wpc_remove_products_without_orders();Этот код проверит каждый товар на наличие завершённых или в обработке заказов и удалит, если таких нет.
Автоматизация через WP-Cron
Чтобы регулярно очищать каталог от неактуальных товаров, добавим задачу в WP-Cron:
if (!wp_next_scheduled('wpc_remove_products_cron')) {
wp_schedule_event(time(), 'daily', 'wpc_remove_products_cron');
}
add_action('wpc_remove_products_cron', 'wpc_remove_products_without_orders');Проверка результата после внедрения
- В базе данных должны отсутствовать товары, у которых нет связанных заказов.
- Проверьте в админке WooCommerce раздел «Товары» — количество товаров должно уменьшиться.
- Для выборочной проверки выполните SQL-запрос из раздела диагностики до и после запуска кода.
- Проверьте логи ошибок PHP, чтобы убедиться в отсутствии сбоев.
Частые ошибки и как их исправить
- Удаляются товары с заказами в статусах, не учтённых в запросе: проверьте параметр
post_statusв SQL, добавьте все релевантные статусы (например, wc-on-hold). - Скрипт не удаляет товары: проверьте, что функция запускается и что пользователь имеет права на удаление постов.
- Высокая нагрузка при большом количестве товаров: разбейте обработку на батчи, например, по 50 товаров за один запуск.
Практические советы по безопасности и производительности
- Запускайте удаление только с правами администратора или через WP-CLI, чтобы избежать случайного удаления.
- Обязательно делайте резервную копию базы данных перед массовым удалением.
- Используйте батчи и транзакции для минимизации нагрузки на базу.
- Логируйте удалённые товары для возможности восстановления при необходимости.
Сравнение подходов: плагин или кастомный код
| Метод | Плюсы | Минусы |
|---|---|---|
| Плагин (например, Bulk Delete) | Удобный интерфейс, готовые фильтры, регулярные обновления | Может быть избыточным, нагрузка, стандартный функционал без кастомизации |
| Кастомный код | Точный контроль, возможность интеграции в бизнес-логику, оптимизация под сайт | Требует навыков разработки, ответственность за безопасность |