Диагностика проблемы: зачем удалять товары после отмены заказа
В стандартном WooCommerce отмена заказа не влияет на наличие товара в каталоге. Однако в некоторых бизнес-сценариях требуется, чтобы товар автоматически удалялся, если заказ отменён — например, при продаже уникальных или лимитированных товаров, которые нельзя продавать повторно.
Основные вопросы диагностики:
- Отменяются ли заказы с товарами, которые нужно удалить?
- Правильно ли определён статус заказа для обработки?
- Есть ли ограничения на удаление (например, товар привязан к другим заказам)?
Пошаговое решение: автоматическое удаление товара после отмены заказа
1. Используем хук смены статуса заказа
WooCommerce предоставляет хук woocommerce_order_status_changed, который срабатывает при смене статуса заказа. На него повесим функцию удаления товаров.
2. Проверяем новый статус и удаляем товары
Удаляем товары, входящие в отменённый заказ, проверяя, что статус изменился именно на cancelled.
add_action('woocommerce_order_status_changed', 'wp5_delete_products_after_cancel', 10, 4);
function wp5_delete_products_after_cancel($order_id, $old_status, $new_status, $order) {
if ($new_status !== 'cancelled') {
return; // Реагируем только на отмену заказа
}
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
// Проверка, существует ли продукт и не является ли он уже удалённым
$product = wc_get_product($product_id);
if (!$product) {
continue;
}
// Дополнительно можно проверить, что товар уникален и не используется в других заказах
// Удаляем товар из базы (без возможности восстановления)
wp_delete_post($product_id, true);
}
}3. Дополнительные проверки перед удалением
Чтобы избежать удаления товаров, связанных с другими активными заказами, добавим проверку наличия других завершённых заказов с этим товаром:
function wp5_is_product_linked_to_active_orders($product_id) {
global $wpdb;
$order_statuses = array('processing', 'completed', 'on-hold');
$placeholders = implode(',', array_fill(0, count($order_statuses), '%s'));
$query = "SELECT COUNT(*) 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->posts} p ON oi.order_id = p.ID
WHERE oim.meta_key = '_product_id'
AND oim.meta_value = %d
AND p.post_status IN ($placeholders)";
$prepared = $wpdb->prepare($query, array_merge(array($product_id), $order_statuses));
$count = $wpdb->get_var($prepared);
return intval($count) > 0;
}
// В основной функции заменяем удаление на проверку:
if (!wp5_is_product_linked_to_active_orders($product_id)) {
wp_delete_post($product_id, true);
}Проверка результата после внедрения
- Создайте тестовый заказ с уникальным товаром.
- Отмените заказ через админ-панель WooCommerce.
- Проверьте, что товар исчез из каталога и из базы данных (через wp-admin или phpMyAdmin).
- Убедитесь, что другие товары, связанные с активными заказами, не удалены.
Частые ошибки и как их исправить
- Удаление не происходит: Проверьте, что хук подключён и функция вызывается (добавьте
error_logдля отладки). - Удаляются товары, которые не нужно удалять: Добавьте проверки на наличие товара в других активных заказах.
- Восстановление удалённых товаров невозможно: Убедитесь, что резервные копии базы есть перед внедрением.
- Проблемы с производительностью: При большом количестве заказов и товаров оптимизируйте запросы к базе, кешируйте результаты.
Практические советы по безопасности и производительности
- Ограничьте удаление товаров только по определённым условиям (например, по категории или метке), чтобы избежать случайных удалений.
- Добавьте логи в отдельный файл для мониторинга автоматических удалений.
- Автоматизируйте создание резервных копий перед массовыми изменениями через WP-Cron или внешние сервисы.
- Используйте транзакции базы данных при удалении, если выполняете комплексные операции.
Сравнение подходов: плагин vs кастомный код
| Критерий | Плагин для удаления товаров | Кастомный код (описанный выше) | Компромисс |
|---|---|---|---|
| Гибкость | Ограничена настройками плагина | Максимальная, можно адаптировать под бизнес-логику | Код требует поддержки разработчика |
| Производительность | Может быть тяжёлым, если плагин универсальный | Оптимизирован под конкретный случай | Необходимо тестировать нагрузку |
| Безопасность | Зависит от качества плагина | Зависит от качества кода | Код можно проверить и адаптировать под стандарты |
| Стоимость | Могут быть платные решения | Требует времени разработчика | Зависит от ресурсов проекта |