Проблема: Нужно динамически менять цену товара в корзине в зависимости от количества
По умолчанию WooCommerce рассчитывает итоговую стоимость товара как цена за единицу × количество. Иногда требуется изменить цену за единицу товара динамически в зависимости от выбранного количества — например, сделать скидку при покупке оптом или повысить цену при небольшом заказе.
Стандартного функционала для этого нет, потребуется использовать хуки WooCommerce и добавить свой код.
Диагностика задачи
Перед тем как писать код, нужно понять, где именно изменять цену:
- На странице товара — динамически менять отображаемую цену при изменении количества.
- В корзине — корректировать цену уже для выбранных товаров.
- При оформлении заказа — чтобы итоговая сумма и данные в заказе были корректны.
Для автоматического изменения цены на стороне корзины и оформления используется фильтр woocommerce_before_calculate_totals. Для изменения цены на странице товара требуется JavaScript и AJAX, чтобы обновлять цену без перезагрузки.
Пошаговое решение: изменение цены в корзине при изменении количества
Рассмотрим самый важный сценарий — изменение цены товара в корзине в зависимости от количества. Например:
- При покупке от 1 до 4 штук – цена базовая.
- От 5 до 9 штук – скидка 10%.
- От 10 и выше – скидка 20%.
Добавим следующий код в файл functions.php активной темы или в собственный плагин:
add_action('woocommerce_before_calculate_totals', 'wptool_dynamic_price_by_quantity', 20, 1);
function wptool_dynamic_price_by_quantity( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Защита от повторного срабатывания
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$quantity = $cart_item['quantity'];
$original_price = $cart_item['data']->get_regular_price();
$new_price = $original_price;
if ( $quantity >= 10 ) {
$new_price = $original_price * 0.8; // скидка 20%
} elseif ( $quantity >= 5 ) {
$new_price = $original_price * 0.9; // скидка 10%
}
$cart_item['data']->set_price( $new_price );
}
}Этот код перебирает все товары в корзине и меняет цену товара на основе его количества. Обратите внимание, что мы используем get_regular_price(), чтобы брать базовую цену, а не текущую, чтобы избежать каскадных изменений.
Как проверить, что код работает
- Добавьте товар в корзину с количеством 1-4 — цена должна быть базовой.
- Увеличьте количество до 5-9 — цена должна автоматически обновиться с 10% скидкой.
- Увеличьте количество до 10 и больше — скидка должна быть 20%.
- Проверьте итоговую сумму в корзине и на странице оформления заказа.
Изменение цены на странице товара с динамическим обновлением
Чтобы цена менялась на странице товара при изменении количества (без перезагрузки), нужно использовать JavaScript и AJAX. Вот упрощенный пример:
add_action('wp_footer', 'wptool_dynamic_price_js');
function wptool_dynamic_price_js() {
if ( ! is_product() ) return;
?>
<script>
jQuery(document).ready(function($) {
var basePrice = parseFloat($('.woocommerce-Price-amount.amount').first().text().replace(/[^0-9.,]/g, '').replace(',', '.'));
$('input.qty').on('change', function() {
var qty = parseInt($(this).val());
var newPrice = basePrice;
if (qty >= 10) {
newPrice = basePrice * 0.8;
} else if (qty >= 5) {
newPrice = basePrice * 0.9;
}
var formattedPrice = newPrice.toFixed(2).replace('.', ',');
$('.woocommerce-Price-amount.amount').first().text(formattedPrice + ' ₽');
});
});
</script>
<?php
}Этот скрипт отслеживает изменение количества и корректирует цену на странице. Для реального проекта потребуется более точная локализация цен и интеграция с WooCommerce JS-событиями.
Частые ошибки и как их исправлять
- Цена не меняется в корзине: проверьте, что хук
woocommerce_before_calculate_totalsиспользуется правильно, и функция вызывается не более одного раза. Добавьте проверкуdid_action, как в примере. - Цена меняется некорректно или не сбрасывается: убедитесь, что вы всегда используете
get_regular_price()для базовой цены, а неget_price(), чтобы избежать рекурсивного изменения. - Изменения цены не сохраняются в заказе: WooCommerce сохраняет цену из корзины в заказ, если вы меняете цену через хук до расчёта итогов. Проверьте, что нет конфликтов с другими плагинами.
- JavaScript не работает на странице товара: убедитесь, что jQuery загружен и селекторы соответствуют вашей теме WooCommerce.
Проверка результата после внедрения
Для проверки правильности работы решения:
- Добавьте товар в корзину с разным количеством, смотрите динамическое изменение цены.
- Оформите заказ и проверьте в админке WooCommerce, что цена заказа соответствует расчетам.
- Используйте инструменты разработчика браузера для отладки JavaScript.
Практические советы по безопасности и производительности
- Не меняйте цены на сервере с задержкой — используйте хук
woocommerce_before_calculate_totalsс низким приоритетом. - Избегайте тяжелых вычислений в этом хукe, чтобы не замедлять страницу корзины.
- Для JavaScript используйте минимизированные и сжатые скрипты, избегайте глобальных переменных.
- Тестируйте изменения на тестовом стенде, чтобы избежать сбоев в работе магазина.
Сравнение вариантов реализации изменения цены
| Вариант | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Серверное изменение цены (хук) | Гарантированно влияет на итог заказа, легко интегрируется | Нет динамического обновления на странице товара без дополнений | Для точного контроля цены в корзине и заказе |
| Клиентское изменение цены (JavaScript) | Динамическое отображение цены пользователю на странице товара | Не влияет на итоговую цену без серверной поддержки | Для улучшения UX при выборе количества товара |
| Плагины скидок и динамической цены | Готовые решения с настройками без кода | Дополнительные расходы, могут замедлять сайт | Для сложных правил и быстрых настроек |