Диагностика задачи: почему нужна динамическая цена по промокоду
В стандартном WooCommerce промокоды влияют на итоговую сумму корзины, но не меняют стоимость товара. Иногда требуется, чтобы цена товара адаптировалась индивидуально уже при добавлении в корзину в зависимости от введённого пользователем кода скидки. Это нужно для сложных акций, например, когда скидка действует только на определённый товар или меняет цену на фиксированную сумму, а не просто процент от корзины.
Как реализовать изменение цены товара по промокоду: подробное решение
1. Используем хук woocommerce_before_calculate_totals для изменения цены в корзине
Этот хук позволяет динамически менять цену товара в корзине перед подсчётом итогов.
add_action('woocommerce_before_calculate_totals', 'custom_change_price_by_coupon', 20, 1);
function custom_change_price_by_coupon( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Проверяем, есть ли в корзине нужный купон
$target_coupon = 'SPECIAL10'; // Замените на ваш код купона
$applied_coupons = WC()->cart->get_applied_coupons();
if ( ! in_array( strtolower($target_coupon), $applied_coupons ) ) {
return; // Купон не применён, ничего менять не нужно
}
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Указываем ID товара, для которого меняем цену
$target_product_id = 123; // замените на ID вашего товара
if ( $cart_item['product_id'] == $target_product_id ) {
// Новая цена товара
$new_price = 50; // фиксированная цена
$cart_item['data']->set_price( $new_price );
}
}
}
2. Добавляем проверку на наличие промокода в форме корзины
Для удобства пользователя можно вывести подсказку о том, какой код применять и что он даёт.
add_action('woocommerce_before_cart', 'custom_coupon_info_message');
function custom_coupon_info_message() {
echo '<div style="padding:10px; background:#d9edf7; border:1px solid #bce8f1; margin-bottom:15px;">Введите код <strong>SPECIAL10</strong>, чтобы получить фиксированную цену 50 руб. на товар с ID 123.</div>';
}
Проверка результата после внедрения кода
- Перейдите в магазин и добавьте в корзину товар с ID, указанным в коде (например, 123).
- В корзине примените купон
SPECIAL10. - Убедитесь, что цена товара изменилась на фиксированную (например, 50 рублей) вместо обычной.
- Проверьте, что без применения купона цена товара остаётся прежней.
- Проверьте поведение на разных товарах — изменение цены должно касаться только нужного товара.
Частые ошибки и как их исправить
- Цена не меняется после применения купона
Проверьте правильность кода купона (учитывайте регистр) и ID товара в коде. Убедитесь, что купон действительно применяется в корзине. - Изменение цены происходит на все товары
Убедитесь, что условиеif ($cart_item['product_id'] == $target_product_id)корректно отфильтровывает нужный товар. - Конфликты с другими плагинами скидок
Проверьте, нет ли других плагинов, которые тоже меняют цену в корзине. Временно отключите их для теста. - Изменение цены не учитывается в заказе
Проверьте, что хук подключён с приоритетом не ниже 20, и что нет ошибок PHP в коде.
Практические советы по безопасности и производительности
- Не храните чувствительные данные в промокодах, используйте их только для активации скидок.
- Старайтесь минимизировать логику в хук
woocommerce_before_calculate_totals, так как он вызывается часто. - Для сложных условий рассмотрите создание собственного плагина, чтобы не загромождать functions.php.
- Тестируйте изменения на staging-сайте, чтобы избежать сбоев на рабочем магазине.
Сравнение способов реализации изменения цены по промокоду
| Метод | Плюсы | Минусы |
|---|---|---|
Хук woocommerce_before_calculate_totals |
Гибко, без плагинов, точечное изменение цены | Требует знаний PHP, может конфликтовать с другими плагинами |
| Плагин скидок (например, WooCommerce Dynamic Pricing) | Простой интерфейс, много настроек | Платные версии, меньше контроля над логикой |
| Использование пользовательских полей и JS для изменения цены на фронтенде | Быстрое визуальное изменение цены | Цена не изменяется на сервере, риск рассинхронизации |