Диагностика задачи: зачем менять стоимость товара в зависимости от доставки
В стандартном WooCommerce цена товара фиксирована и не зависит от выбранного способа доставки. Однако в ряде случаев необходимо автоматически корректировать стоимость товара в корзине в зависимости от выбранного способа доставки. Например, при экспресс-доставке цена товара может увеличиваться из-за дополнительных расходов, или при самовывозе — наоборот, снижаться.
Основная проблема — стандартное поведение WooCommerce не предусматривает изменение цены товара после выбора способа доставки, поэтому требуется кастомный код.
Пошаговое решение: как реализовать автоматическое изменение цены товара при выборе способа доставки
1. Использование хука woocommerce_before_calculate_totals
Этот хук позволяет изменять цену товаров в корзине перед пересчетом итогов. Мы можем добавить проверку выбранного способа доставки и, в зависимости от него, корректировать цену.
add_action('woocommerce_before_calculate_totals', 'custom_change_price_based_on_shipping', 20, 1);
function custom_change_price_based_on_shipping($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (did_action('woocommerce_before_calculate_totals') >= 2) return;
// Получаем выбранный способ доставки
$chosen_methods = WC()->session->get('chosen_shipping_methods');
if (empty($chosen_methods)) return;
$chosen_shipping = $chosen_methods[0];
// Проходим по товарам в корзине
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$original_price = $cart_item['data']->get_regular_price();
// Пример: если выбран способ доставки 'express_shipping', увеличиваем цену на 10%
if ($chosen_shipping === 'express_shipping') {
$new_price = $original_price * 1.10; // +10%
$cart_item['data']->set_price($new_price);
} elseif ($chosen_shipping === 'local_pickup') {
// при самовывозе уменьшаем цену на 5%
$new_price = $original_price * 0.95; // -5%
$cart_item['data']->set_price($new_price);
} else {
// для всех остальных способов возвращаем оригинальную цену
$cart_item['data']->set_price($original_price);
}
}
}2. Определение ID или slug способа доставки
Для точной работы скрипта нужно узнать точный идентификатор способа доставки. Его можно найти в админке WooCommerce (Настройки > Доставка > Зоны доставки) или через вывод массива WC()->session->get('chosen_shipping_methods') с помощью error_log(print_r(...)).
3. Обработка динамического обновления цены без перезагрузки страницы
Чтобы изменения стоимости отображались сразу после выбора способа доставки на странице корзины или оформления заказа, нужно убедиться, что AJAX обновляет корзину. В большинстве тем и шаблонов WooCommerce это происходит автоматически.
Проверка результата после внедрения
- Добавьте товар в корзину.
- Перейдите на страницу корзины или оформления заказа.
- Выберите способ доставки, например, «Экспресс-доставка».
- Убедитесь, что цена товара изменилась в соответствии с заданным процентом.
- Смените способ доставки на «Самовывоз» — цена должна уменьшиться.
- Выберите другой способ — цена возвращается к оригиналу.
Частые ошибки и причины их возникновения
- Изменения цены не применяются или сбрасываются: Возможно, в хуке происходит повторное срабатывание, из-за чего цены меняются несколько раз. Решение — использовать проверку
did_action('woocommerce_before_calculate_totals') < 2. - Цена меняется, но итоговая сумма в корзине не обновляется: Отсутствует AJAX-обновление корзины при смене способа доставки. Требуется проверить тему на поддержку AJAX в корзине.
- Неверный идентификатор способа доставки: Нужно убедиться, что slug способа доставки совпадает с тем, который используется в коде.
- Изменение цены влияет на отображение в других местах (например, на странице товара): Изменяйте цену только для объектов в корзине, не меняйте глобальные цены товара.
Практические советы по безопасности и производительности
- Не сохраняйте изменённые цены в базу данных — меняйте цену только в объекте
WC_Productв корзине. - Используйте минимально необходимый приоритет для хука (например, 20), чтобы избежать конфликтов с другими плагинами.
- Проверяйте, что функция не вызывается в админке или при AJAX-запросах, не связанных с фронтендом.
Сравнение вариантов реализации
| Метод | Преимущества | Недостатки |
|---|---|---|
Код на хуке woocommerce_before_calculate_totals | Гибкость, не требует плагинов, прямое управление ценами | Требует навыков программирования, возможны конфликты с другими плагинами |
| Плагины для управления ценами в зависимости от доставки | Простота настройки, поддержка, готовые решения | Могут быть платными, нагружают сайт, ограничены функционалом |
| Изменение цен через JS на фронтенде | Моментальное обновление UI, без вмешательства в серверный код | Не влияет на реальные данные заказа, легко обойти, небезопасно |