Диагностика проблемы: зачем удалять товары без заказов
В интернет-магазинах на WooCommerce может скапливаться большое количество товаров, которые не пользуются спросом и не были заказаны ни разу. Это увеличивает нагрузку на базу данных, замедляет работу сайта и усложняет управление каталогом. Чтобы поддерживать базу в чистоте, полезно автоматически удалять такие товары через определённый промежуток времени.
Как определить товары без заказов в WooCommerce
Для начала нужно понять, какие товары не имеют заказов. Основная связь между заказами и товарами хранится в таблицах wp_woocommerce_order_items и wp_woocommerce_order_itemmeta. Простой SQL-запрос поможет получить ID товаров, которые были заказаны:
SELECT DISTINCT order_item_id, meta_value as product_id
FROM wp_woocommerce_order_items
JOIN wp_woocommerce_order_itemmeta ON wp_woocommerce_order_items.order_item_id = wp_woocommerce_order_itemmeta.order_item_id
WHERE meta_key = '_product_id';Чтобы найти товары без заказов — нужно получить список всех товаров и исключить из него те, что встречаются в заказах.
Пошаговое решение: автоматическое удаление товаров без заказов
1. Создайте функцию для проверки товаров без заказов
function get_products_without_orders($days = 30) {
global $wpdb;
// Получаем ID товаров, которые были заказаны за последние $days дней
$date_threshold = date('Y-m-d H:i:s', strtotime("-{$days} days"));
$ordered_products = $wpdb->get_col($wpdb->prepare(
"SELECT DISTINCT meta_value FROM {$wpdb->prefix}woocommerce_order_items oi
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
INNER JOIN {$wpdb->prefix}posts p ON oi.order_id = p.ID
WHERE oim.meta_key = '_product_id' AND p.post_type = 'shop_order' AND p.post_status IN ('wc-completed', 'wc-processing') AND p.post_date >= %s",
$date_threshold
));
// Получаем все ID товаров
$all_products = get_posts([
'post_type' => 'product',
'posts_per_page' => -1,
'fields' => 'ids',
'post_status' => 'publish',
]);
// Возвращаем товары, которых нет в заказах
return array_diff($all_products, $ordered_products);
}2. Функция удаления товаров
function delete_products_by_ids(array $product_ids) {
foreach ($product_ids as $product_id) {
wp_delete_post($product_id, true); // Принудительно удаляем без возможности восстановления
}
}3. Настройка WP-Cron для автоматизации
Добавьте в functions.php или собственный плагин следующий код для еженедельного запуска задачи удаления товаров без заказов:
add_action('wp_delete_products_without_orders', 'wp_delete_unused_products_cron');
function wp_delete_unused_products_cron() {
$products_to_delete = get_products_without_orders(30); // Товары без заказов за последние 30 дней
if (!empty($products_to_delete)) {
delete_products_by_ids($products_to_delete);
}
}
// Регистрируем событие при активации плагина/темы
function wp_schedule_delete_products_event() {
if (!wp_next_scheduled('wp_delete_products_without_orders')) {
wp_schedule_event(time(), 'weekly', 'wp_delete_products_without_orders');
}
}
add_action('wp', 'wp_schedule_delete_products_event');
// Снимаем расписание при деактивации
function wp_unschedule_delete_products_event() {
$timestamp = wp_next_scheduled('wp_delete_products_without_orders');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wp_delete_products_without_orders');
}
}Проверка результата после внедрения
- Через панель администратора WooCommerce зайдите в раздел Товары и проверьте, что товары без заказов старше 30 дней исчезли.
- Запустите вручную функцию с помощью WP-CLI:
wp eval 'wp_delete_unused_products_cron();'и проверьте удаление. - Проверьте лог ошибок PHP и WooCommerce на предмет проблем при удалении.
Частые ошибки и как их исправить
- Не удаляются товары: проверьте права пользователя, под которым запущен WP-Cron или WP-CLI. Убедитесь, что функция
wp_delete_postвызывается с правильным ID и вторым параметромtrueдля безвозвратного удаления. - Товары с заказами тоже удаляются: проверьте корректность SQL-запроса. Убедитесь, что статусы заказов правильно фильтруются (например, исключая отменённые)
- Нагрузка на базу данных: для магазинов с тысячами товаров запросы могут быть тяжёлыми. Используйте пагинацию при выборке товаров.
Практические советы по безопасности и производительности
- Перед удалением товаров делайте резервную копию базы данных.
- Проверяйте статус заказов — учитывайте только оплаченные и обработанные.
- Оптимизируйте запросы с помощью индексов в базе данных.
- Для больших магазинов разбивайте удаление на партии (например, по 50 товаров за раз).
- Логируйте удалённые товары для последующего аудита.
Сравнение вариантов удаления товаров без заказов
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Ручное удаление через админку | Поиск и удаление товаров вручную | Простой способ без кода | Трудоёмко, неэффективно при большом каталоге |
| Плагин для очистки базы | Использование готовых плагинов для удаления неактивных товаров | Удобство, дополнительные функции | Может замедлять сайт, лишний плагин |
| Кодовое решение с WP-Cron (данный метод) | Автоматизация удаления через собственный скрипт | Контроль, гибкость, отсутствие лишних плагинов | Необходимы навыки разработки, риск ошибок |