Диагностика проблемы: зачем удалять товары без заказов
В интернет-магазине на WooCommerce с течением времени накапливаются товары, которые так и не были куплены. Это может привести к захламлению каталога, усложнению администрирования и замедлению работы сайта, особенно при большом количестве товаров. Автоматическое удаление таких товаров настраивается, чтобы поддерживать базу данных в актуальном состоянии и улучшать производительность.
Как определить товары без заказов
Для того чтобы удалить товары без заказов, необходимо сначала точно определить, какие товары не были проданы ни разу. WooCommerce хранит данные о заказах в таблицах wp_posts (заказы — тип записи shop_order) и wp_woocommerce_order_items (позиции товаров в заказах).
Простейший способ — запросить ID товаров, не встречающихся в позициях заказов:
SELECT p.ID FROM wp_posts p
WHERE p.post_type = 'product'
AND p.ID NOT IN (
SELECT order_item_meta.meta_value FROM wp_woocommerce_order_items items
JOIN wp_woocommerce_order_itemmeta order_item_meta ON items.order_item_id = order_item_meta.order_item_id
WHERE items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
);Этот запрос возвращает ID товаров без заказов. Но для автоматизации потребуется PHP-скрипт.
Пошаговое решение: скрипт для автоматического удаления товаров без заказов
1. Создаем WP-CLI команду для удаления
WP-CLI — удобный инструмент для автоматизации задач. Вот пример команды для удаления товаров без заказов старше определенного времени (например, 90 дней):
if ( defined('WP_CLI') && WP_CLI ) {
WP_CLI::add_command('wc-delete-unused-products', function($args, $assoc_args) {
$days = isset($assoc_args['days']) ? intval($assoc_args['days']) : 90;
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
global $wpdb;
$product_ids = $wpdb->get_col($wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
WHERE p.post_type = 'product'
AND p.post_date < %s
AND p.ID NOT IN (
SELECT DISTINCT order_item_meta.meta_value FROM {$wpdb->prefix}woocommerce_order_items items
JOIN {$wpdb->prefix}woocommerce_order_itemmeta order_item_meta ON items.order_item_id = order_item_meta.order_item_id
WHERE items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
)",
$date_threshold
));
$count = 0;
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true); // true — безвозвратно
$count++;
}
WP_CLI::success("Удалено товаров без заказов старше {$days} дней: {$count}");
});
}2. Запуск команды
После добавления кода в файл плагина или в functions.php темы, запустите из терминала в корне сайта:
wp wc-delete-unused-products --days=90Это удалит все товары без заказов, которые были созданы более 90 дней назад. Параметр --days можно менять.
Проверка результата после внедрения
- Перед запуском выполните полный бэкап базы данных.
- Запустите SQL-запрос из раздела диагностики и сравните количество ID товаров до и после.
- Проверьте в админке WooCommerce список товаров — удаленные должны исчезнуть.
- Для теста можно создать тестовый товар без заказов старше 90 дней (через изменение даты публикации) и проверить, удаляется ли он.
Частые ошибки и как их исправить
- Ошибка: Нет доступа к WP-CLI или команда не распознается.
Решение: Убедитесь, что WP-CLI установлен и настроен, либо используйте аналогичный скрипт с запуском через cron и PHP. - Ошибка: Товары не удаляются, хотя запрос возвращает ID.
Решение: Проверьте права пользователя, под которым запускается скрипт, и параметрыwp_delete_post. Возможно, лучше использовать принудительное удаление (force_delete=true). - Ошибка: Удаляются нужные товары.
Решение: Добавьте в запрос дополнительную фильтрацию по статусу товара (например, толькоpublish), или добавьте мета-поле для исключения.
Практические советы по безопасности и производительности
- Запускайте массовое удаление в периоды наименьшей нагрузки.
- Обязательно делайте бэкапы перед массовым удалением.
- Рассмотрите использование
wp_delete_postс параметромforce_delete = true, чтобы избежать попадания товаров в корзину. - Для больших магазинов разбивайте удаление на партии по 100-200 товаров, чтобы избежать таймаутов.
- Используйте транзакции в базе, если реализуете удаление напрямую через SQL.
Сравнение подходов для удаления товаров без заказов
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| SQL-запрос и массовое удаление | Быстро, без загрузки WordPress | Риск ошибок, сложность в учете связей | SELECT + DELETE по ID |
| WP-CLI команда | Использует API WP, безопаснее, легко настраивается | Требуется доступ к командной строке | wp wc-delete-unused-products --days=90 |
| Плагин с функцией удаления | Удобно для пользователей без доступа к серверу | Может нагружать сайт при большом количестве товаров | Пользовательский плагин с кнопкой "Удалить" |