Диагностика проблемы: почему стандартные скидки WooCommerce не подходят
WooCommerce предоставляет стандартные возможности для создания скидок через купоны и правила в корзине, однако в некоторых случаях требуется более гибкий и автоматизированный механизм изменения цены товара в зависимости от сложных условий. Например, если скидка зависит от нескольких параметров одновременно (категория товара, количество в заказе, роль пользователя) или если нужно динамически менять цену без применения купонов.
В таких ситуациях стандартные методы не позволяют реализовать бизнес-логику без кастомного кода.
Пошаговое решение: как программно менять цену товара в корзине WooCommerce
1. Используем хук woocommerce_before_calculate_totals
Этот хук позволяет изменить цену товара перед расчетом итогов корзины.
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_discount', 20, 1);
function custom_dynamic_price_discount( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
$quantity = $cart_item['quantity'];
// Пример условия: скидка 15% если количество больше 3
if ( $quantity > 3 ) {
$new_price = $original_price * 0.85; // 15% скидка
$product->set_price( $new_price );
} else {
// Вернуть исходную цену, если условие не выполнено
$product->set_price( $original_price );
}
}
}
2. Добавление условий для роли пользователя и категории товара
Чтобы расширить логику, добавим проверку роли пользователя и категории товара:
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_discount_extended', 20, 1);
function custom_dynamic_price_discount_extended( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$user = wp_get_current_user();
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
$quantity = $cart_item['quantity'];
// Проверяем роль пользователя
if ( in_array( 'wholesale_customer', (array) $user->roles ) ) {
// Проверяем категорию товара
if ( has_term( 'bulk-items', 'product_cat', $product->get_id() ) ) {
// Устанавливаем скидку 25% если количество больше 10
if ( $quantity > 10 ) {
$product->set_price( $original_price * 0.75 );
} else {
$product->set_price( $original_price );
}
}
}
}
}
Проверка результата после внедрения
- Добавьте в корзину товары с разным количеством, в том числе свыше пороговых значений (например, больше 3 или 10 штук).
- Залогиньтесь под разными пользователями с разными ролями (например, розничный покупатель и wholesale_customer).
- Проверьте, что цены в корзине корректно изменяются согласно логике.
- Используйте инструменты разработчика браузера для проверки, что цена товара обновляется динамически, и итоговая сумма рассчитывается правильно.
Частые ошибки и как их исправить
- Цена не меняется в корзине. Проверьте, правильно ли подключен хук
woocommerce_before_calculate_totalsи не блокирует ли другие плагины изменение цены. - Цена сбрасывается после обновления страницы. Убедитесь, что вы не используете кеширование корзины или страниц, где отображается корзина.
- Цена меняется для всех пользователей. Проверьте корректность проверки роли пользователя. Для теста можно вывести роли через
error_log(print_r(wp_get_current_user()->roles, true));. - Изменение цены влияет на отображение в админке. Добавьте проверку
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;в функцию, чтобы избежать изменения цены в административной части.
Практические советы по безопасности и производительности
- Не храните изменённые цены в базе данных, изменяйте только на уровне сессии и корзины.
- Минимизируйте количество условий и вызовов функций внутри цикла по товарам корзины для ускорения обработки.
- Используйте кэширование ролей пользователя вне цикла, чтобы не вызывать
wp_get_current_user()многократно. - Тестируйте изменения на тестовом сайте, а не на живом магазине.
Сравнение методов реализации изменения цены
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Стандартные купоны WooCommerce | Простота использования, нет кода | Ограниченная логика, не подходит для сложных условий | Простые скидки для всех пользователей или по купону |
| Правила корзины (WooCommerce Discounts) | Больше гибкости, можно комбинировать условия | Сложность настройки, нет динамической цены товара | Скидка на корзину, но не изменение цены товара |
Кастомный код на woocommerce_before_calculate_totals |
Максимальная гибкость, динамическое изменение цены | Требует навыков PHP, риск ошибок | Сложные бизнес-правила, автоматизация скидок |