Диагностика задачи: зачем изменять скидки динамически в WooCommerce
В стандартном WooCommerce управление скидками ограничено купонами и фиксированными правилами. Иногда требуется изменить скидку прямо на странице корзины в зависимости от условий, например, суммы заказа, количества товаров или пользовательских данных. Хук woocommerce_before_cart_totals позволяет добавить кастомную логику перед выводом итогов корзины.
Пошаговое решение: динамическое изменение скидок через хук woocommerce_before_cart_totals
1. Добавление пользовательской функции в functions.php
Откройте файл functions.php вашей дочерней темы или используйте плагин для пользовательских функций.
add_action('woocommerce_before_cart_totals', 'dynamic_cart_discount');
function dynamic_cart_discount() {
$cart = WC()->cart;
if ( ! $cart ) return;
// Пример условия: скидка 10% если сумма корзины больше 5000 рублей
$threshold = 5000;
$discount_percent = 10;
$cart_total = $cart->get_subtotal();
if ( $cart_total > $threshold ) {
$discount_amount = $cart_total * ($discount_percent / 100);
// Добавляем скидку вручную
$cart->add_fee( __('Динамическая скидка', 'woocommerce'), -$discount_amount );
}
}
2. Объяснение кода
- Получаем объект корзины
WC()->cart. - Проверяем условие — сумма корзины больше 5000.
- Вычисляем сумму скидки как 10% от суммы.
- Добавляем отрицательный сбор через
add_feeс отрицательным значением — это и есть скидка.
3. Альтернативный подход: использование 'woocommerce_cart_calculate_fees'
Иногда удобнее применять скидки на этапе пересчёта корзины:
add_action('woocommerce_cart_calculate_fees', 'dynamic_cart_discount_fees');
function dynamic_cart_discount_fees( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
$threshold = 5000;
$discount_percent = 10;
$cart_total = $cart->get_subtotal();
if ( $cart_total > $threshold ) {
$discount_amount = $cart_total * ($discount_percent / 100);
$cart->add_fee( __('Динамическая скидка', 'woocommerce'), -$discount_amount );
}
}
Проверка результата после внедрения
- Добавьте товары в корзину с суммой свыше 5000 рублей.
- Перейдите в корзину и убедитесь, что в блоке итогов появилась строка с названием "Динамическая скидка" и отрицательной суммой.
- Убедитесь, что итоговая сумма пересчитана с учётом скидки.
- Если сумма корзины меньше порога — скидка не должна отображаться.
Частые ошибки и как их исправить
- Скидка не появляется в корзине. Проверьте, что хук добавлен корректно и функция подключена в
functions.phpактивной темы или плагина. Убедитесь, что корзина не пуста. - Сумма скидки рассчитывается не так, как ожидалось. Убедитесь, что используете
get_subtotal(), а неget_total()илиget_cart_contents_total(). Разница в учёте налогов и прочего. - Скидка применяется несколько раз. Проверьте, что функция не вызывается несколько раз подряд. Добавьте проверку или сброс флагов, если нужно.
- Конфликты с другими плагинами скидок. Проверьте взаимодействие с другими плагинами, отключая их поочерёдно.
Практические советы по безопасности и производительности
- Для повышения производительности избегайте тяжелых запросов и сложных операций внутри функции, вызываемой на каждом обновлении корзины.
- Проверяйте, что код не выполняется в административной части, добавляя условие
if ( is_admin() && ! defined('DOING_AJAX') ) return;. - Для безопасности убедитесь, что пользовательские данные не используются напрямую без проверки.
Сравнение вариантов реализации динамических скидок в WooCommerce
| Метод | Плюсы | Минусы |
|---|---|---|
Хук woocommerce_before_cart_totals |
Простота реализации, скидка видна сразу перед итогами | Скидка добавляется визуально, может не учитываться во всех расчётах |
Хук woocommerce_cart_calculate_fees |
Скидка считается на этапе пересчёта, корректно влияет на итоговую цену | Нужна аккуратность, чтобы избежать дублирования скидок |