Проблема: повторное создание заказов при наличии активного
В интернет-магазинах на WooCommerce часто возникает ситуация, когда пользователь случайно или по ошибке создает несколько заказов на один и тот же товар, не завершив предыдущий. Это приводит к избыточной нагрузке на базу данных, путанице в заказах и неудобствам для менеджеров и клиентов.
Диагностика проблемы
Чтобы определить, есть ли у пользователя активный (открытый) заказ, нужно проверить статус существующих заказов. В WooCommerce статус заказа, который еще не завершен, обычно pending, processing или on-hold. Если новый заказ создается, не проверяя это, дублирование неизбежно.
Диагностировать можно так:
- В админке WooCommerce перейти в Заказы и посмотреть, есть ли у пользователя заказы со статусами, отличными от
completedилиcancelled. - Использовать SQL-запрос для проверки активных заказов конкретного пользователя.
SELECT ID, post_status FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ('wc-pending', 'wc-processing', 'wc-on-hold') AND ID IN (SELECT post_id FROM wp_postmeta WHERE meta_key = '_customer_user' AND meta_value = USER_ID);Где USER_ID - ID пользователя в WordPress.
Пошаговое решение: блокировка повторного создания заказа
Для предотвращения повторного создания заказа реализуем проверку на хуке 'woocommerce_add_to_cart_validation', который срабатывает перед добавлением товара в корзину.
Основная идея: если у пользователя есть активный заказ, запретить добавление новых товаров с сообщением об ошибке.
add_filter('woocommerce_add_to_cart_validation', 'wpbono_prevent_duplicate_order', 10, 3);
function wpbono_prevent_duplicate_order($passed, $product_id, $quantity) {
if (!is_user_logged_in()) {
return $passed; // Проверка только для авторизованных
}
$user_id = get_current_user_id();
$active_statuses = array('wc-pending', 'wc-processing', 'wc-on-hold');
$args = array(
'customer_id' => $user_id,
'status' => $active_statuses,
'limit' => 1
);
$orders = wc_get_orders($args);
if (!empty($orders)) {
wc_add_notice('У вас уже есть активный заказ. Пожалуйста, завершите его перед созданием нового.', 'error');
return false;
}
return $passed;
}Этот код проверяет, есть ли у пользователя активный заказ, и запрещает добавлять товары в корзину при наличии такого заказа.
Проверка результата после внедрения
- Авторизуйтесь под пользователем с активным заказом.
- Попробуйте добавить товар в корзину.
- Должно появиться сообщение об ошибке и товар не добавится.
- Для пользователя без активных заказов добавление происходит без проблем.
Частые ошибки и как исправить
- Ошибка: Пользователь не видит сообщение об ошибке.
Причина: В теме или плагинах отключена вывод сообщений WooCommerce.
Решение: Убедитесь, что в шаблоне присутствуетdo_action('woocommerce_before_cart');илиwc_print_notices(). - Ошибка: Проверка не работает для гостей.
Причина: В коде проверкаis_user_logged_in()не пропускает гостей.
Решение: Добавьте отдельную логику для гостей, например, по IP или сессии, если необходимо. - Ошибка: Отсутствие корректной проверки статусов заказа.
Причина: Используются неправильные статусы или пропущены важные.
Решение: Используйте полный список статусов, которые считаются активными в вашем магазине.
Практические советы по безопасности и производительности
- Для ускорения запроса используйте
wc_get_ordersс ограничениемlimit. - Не храните логику проверки в шаблонах, а вынесите в плагин или functions.php.
- Для больших магазинов с миллионами заказов рассмотрите кэширование результатов проверки по пользователю на короткий промежуток.
- Регулярно очищайте устаревшие заказы, чтобы не загромождать базу.
Альтернативные подходы: плагин vs. кастомный код
| Подход | Плюсы | Минусы |
|---|---|---|
| Кастомный код | Легко адаптируется под конкретные задачи; минимальная нагрузка; без лишних плагинов. | Требует знаний PHP; может конфликтовать с обновлениями WooCommerce. |
| Плагин (например, WooCommerce Order Restriction) | Готовое решение с настройками; поддержка разработчика. | Может быть избыточным; дополнительная нагрузка; необходимость обновлений. |