Диагностика задачи: зачем удалять варианты товаров после первого заказа
В WooCommerce иногда возникает необходимость автоматически удалить вариации товаров, которые были заказаны хотя бы один раз. Например, если магазин предлагает ограниченные серии или эксклюзивные варианты, которые после продажи первой единицы должны исчезнуть из каталога. Ручное удаление неудобно и чревато ошибками.
Как проверить, что вариант товара был заказан
В WooCommerce информация о заказах хранится в таблицах wp_posts (заказы) и wp_woocommerce_order_items (позиции заказа). Для определения, был ли заказан конкретный вариационный товар, достаточно проверить наличие заказов с этим ID вариации как product_id.
Пример запроса для проверки через WP_Query
$variation_id = 123; // ID вариации
$orders = wc_get_orders(array(
'limit' => 1,
'status' => array('completed', 'processing', 'on-hold'),
'meta_query' => array(
array(
'key' => '_product_id',
'value' => $variation_id,
'compare' => '='
),
),
));
if (!empty($orders)) {
// Вариация была заказана
}Однако WooCommerce не хранит напрямую _product_id в метаданных заказа, поэтому для точного поиска лучше использовать WC_Order_Item_Product и пройти по всем заказам:
function variation_has_orders($variation_id) {
$args = array(
'limit' => -1,
'status' => array('completed', 'processing', 'on-hold'),
);
$orders = wc_get_orders($args);
foreach ($orders as $order) {
foreach ($order->get_items() as $item) {
if ($item->get_product_id() == $variation_id) {
return true;
}
}
}
return false;
}Пошаговое решение: автоматическое удаление вариаций после первого заказа
Для автоматизации процесса добавим хук на событие создания заказа и проверим, есть ли вариации, которые впервые были заказаны. Если да — удалим их.
Код для functions.php или собственного плагина
add_action('woocommerce_thankyou', 'remove_variations_after_first_order', 10, 1);
function remove_variations_after_first_order($order_id) {
if (!$order_id) return;
$order = wc_get_order($order_id);
if (!$order) return;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (!$product || $product->get_type() !== 'variation') continue;
$variation_id = $product->get_id();
// Проверяем, был ли этот вариант заказан ранее
if (!variation_has_orders_before($order_id, $variation_id)) {
// Удаляем вариацию
wp_delete_post($variation_id, true);
}
}
}
function variation_has_orders_before($current_order_id, $variation_id) {
$args = array(
'limit' => -1,
'status' => array('completed', 'processing', 'on-hold'),
'exclude' => array($current_order_id),
);
$orders = wc_get_orders($args);
foreach ($orders as $order) {
foreach ($order->get_items() as $item) {
if ($item->get_product_id() == $variation_id) {
return true;
}
}
}
return false;
}Проверка результата после внедрения
- Сделайте тестовый заказ вариации, которую еще не заказывали.
- После подтверждения заказа проверьте в админке WooCommerce, что вариация удалена.
- Попробуйте сделать заказ вариации, которая уже была заказана ранее — она не должна удаляться.
- Проверьте, что удаление не затрагивает основной товар или другие вариации.
Частые ошибки и как их исправить
- Не удаляется вариация: проверьте, что хук
woocommerce_thankyouсрабатывает и что ID вариаций корректно определяется. - Удаляются все вариации: убедитесь, что функция
variation_has_orders_beforeправильно исключает текущий заказ и проверяет именно предшествующие заказы. - Права доступа: функция
wp_delete_postудаляет вариацию навсегда; убедитесь, что у пользователя, под которым работает PHP, есть права на удаление постов. - Потеря данных: если вариации связаны с другими объектами (например, отзывы), учтите, что они тоже будут удалены.
Практические советы по безопасности и производительности
- Для ускорения проверки заказов можно кешировать результаты проверки
variation_has_orders_before, например, с помощью transient API WordPress. - Обязательно делайте резервное копирование базы данных перед внедрением автоматического удаления.
- Если магазин большой, ограничьте количество проверяемых заказов в
wc_get_ordersили реализуйте поиск через прямые запросы к базе с индексами. - Рассмотрите уведомление админа после удаления вариации для контроля и аудита действий.
Сравнение способов реализации автоматического удаления вариаций
| Метод | Плюсы | Минусы | Компромисс |
|---|---|---|---|
| PHP-хук на создание заказа | Полный контроль, без плагинов | Нагрузка при большом количестве заказов | Добавить кеширование для оптимизации |
| SQL-запрос для поиска вариаций | Быстрее при больших данных | Сложность поддержки, риск ошибок | Использовать только для отчётов и проверок |
| Использование плагина автоматизации | Простота настройки | Может быть избыточно и влиять на производительность | Использовать при отсутствии ресурсов на кастомный код |