Диагностика проблемы: зачем ограничивать покупки по пользователям в WooCommerce
Иногда требуется ограничить количество товаров, которые конкретный пользователь может приобрести за один заказ или в целом на сайте. Это полезно для оптовиков, ограниченных акций, предотвращения мошенничества или контроля складских запасов для отдельных клиентов. WooCommerce по умолчанию не предоставляет гибких настроек таких ограничений, поэтому приходится добавлять кастомные решения.
Пошаговое решение: установка ограничений на количество товаров по пользователю
1. Ограничение количества товара в корзине для отдельных пользователей
Для начала реализуем ограничение максимального количества одного товара в корзине для определённой роли или пользователя. Ниже пример кода для functions.php темы или кастомного плагина:
add_filter('woocommerce_add_to_cart_validation', 'limit_product_quantity_per_user', 10, 3);
function limit_product_quantity_per_user($passed, $product_id, $quantity) {
// Список ID пользователей или ролей, для которых ограничение
$restricted_user_ids = array(5, 12); // ID пользователей
$restricted_roles = array('subscriber'); // роли
$user = wp_get_current_user();
if (in_array($user->ID, $restricted_user_ids) || array_intersect($restricted_roles, $user->roles)) {
$max_qty = 3; // Максимальное количество
// Проверка уже добавленного количества в корзине
$cart = WC()->cart->get_cart();
$current_qty = 0;
foreach ($cart as $cart_item) {
if ($cart_item['product_id'] == $product_id) {
$current_qty += $cart_item['quantity'];
}
}
if ($current_qty + $quantity > $max_qty) {
wc_add_notice(sprintf('Вы можете добавить не более %d единиц этого товара.', $max_qty), 'error');
return false;
}
}
return $passed;
}2. Ограничение общей суммы заказа по пользователю
Если нужно ограничить не количество товара, а сумму заказа, добавьте следующий код:
add_action('woocommerce_checkout_process', 'limit_order_total_for_users');
function limit_order_total_for_users() {
$user = wp_get_current_user();
$restricted_user_ids = array(5,12);
$restricted_roles = array('subscriber');
$max_total = 10000; // Максимальная сумма заказа в рублях
if (in_array($user->ID, $restricted_user_ids) || array_intersect($restricted_roles, $user->roles)) {
$cart_total = WC()->cart->total;
if ($cart_total > $max_total) {
wc_add_notice(sprintf('Максимальная сумма заказа для вас — %s руб.', number_format($max_total, 0, '.', ' ')), 'error');
}
}
}3. Ограничение по общему числу покупок товара пользователем (история заказов)
Этот шаг сложнее: нужно проверить, сколько товара пользователь уже купил и запретить превысить лимит.
function get_user_purchased_qty( $user_id, $product_id ) {
$qty = 0;
$customer_orders = wc_get_orders(array(
'customer' => $user_id,
'limit' => -1,
'status' => array('completed','processing'),
));
foreach ( $customer_orders as $order ) {
foreach ( $order->get_items() as $item ) {
if ( $item->get_product_id() == $product_id ) {
$qty += $item->get_quantity();
}
}
}
return $qty;
}
add_filter('woocommerce_add_to_cart_validation', 'limit_total_product_purchases', 20, 3);
function limit_total_product_purchases($passed, $product_id, $quantity) {
$user = wp_get_current_user();
$restricted_user_ids = array(5,12);
$restricted_roles = array('subscriber');
$max_purchases = 5;
if (in_array($user->ID, $restricted_user_ids) || array_intersect($restricted_roles, $user->roles)) {
$already_purchased = get_user_purchased_qty($user->ID, $product_id);
if (($already_purchased + $quantity) > $max_purchases) {
wc_add_notice(sprintf('Вы можете купить не более %d единиц этого товара за всё время.', $max_purchases), 'error');
return false;
}
}
return $passed;
}Проверка результата после внедрения
- Авторизуйтесь под пользователем, попавшим под ограничения.
- Попробуйте добавить в корзину товар сверх лимита — появится ошибка.
- Попробуйте оформить заказ на сумму, превышающую лимит (если ограничивали сумму) — при оформлении заказа появится предупреждение и блокировка.
- Проверьте, что для пользователей без ограничений ограничений нет.
Частые ошибки и как их исправить
- Ошибка: Ограничения не применяются. Проверьте, что код добавлен в активную тему или плагин и нет конфликтов с другими хуками.
- Ошибка: Пользователь видит ограничения, хотя не должен. Проверьте правильность ID пользователей и ролей в массивах
$restricted_user_idsи$restricted_roles. - Ошибка: Некорректный подсчет количества в корзине. Убедитесь, что используете правильные ключи массива корзины:
product_idдля ID товара, и суммируете текущие количества. - Ошибка: Производительность падает при проверке истории заказов. Кэшируйте результаты или ограничьте выборку заказов по дате.
Практические советы по безопасности и производительности
- Используйте
wc_add_noticeдля вывода ошибок — это штатный способ WooCommerce информировать пользователя без прерывания скрипта. - Кэшируйте результаты подсчета покупок пользователя, чтобы избежать повторных запросов к базе данных.
- Тестируйте ограничения на staging-сайте, чтобы не повлиять на продажи в рабочем магазине.
- Разграничивайте права по ролям, а не только по ID пользователей — это проще в управлении.
Сравнение вариантов реализации ограничения покупок в WooCommerce
| Метод | Плагин | Код | Компромисс |
|---|---|---|---|
| Ограничение по количеству в корзине | WooCommerce Min/Max Quantities | Простой фильтр woocommerce_add_to_cart_validation | Код гибче, без сторонних зависимостей |
| Ограничение по сумме заказа | WooCommerce Order Minimum/Maximum Amount | Хук woocommerce_checkout_process | Плагин удобен для настройки без кода |
| Ограничение по общей истории покупок | Отсутствует простое решение | Кастомный код с wc_get_orders | Нагрузка на БД, требует оптимизации |