WooCommerce: автоматическое изменение стоимости товара при изменении количества в корзине

Диагностика задачи: почему нужно менять стоимость товара динамически при изменении количества

По умолчанию WooCommerce рассчитывает стоимость товара в корзине как цена товара × количество. Однако бывают задачи, когда необходимо автоматически менять стоимость товара по формуле, зависящей от количества. Например, при покупке 3 и более единиц цена за штуку снижается, или применяется дополнительная скидка, либо стоимость рассчитывается по сложной формуле.

Проверить, что расчет стоимости стандартный, можно через просмотр корзины и отладку хука woocommerce_before_calculate_totals. Если цена не меняется, значит нужно реализовать кастомную логику.

Как реализовать автоматическое изменение стоимости товара в WooCommerce при изменении количества

Использование хука woocommerce_before_calculate_totals

Этот хук вызывается перед подсчетом итогов корзины. В нем можно перебрать товары в корзине и изменить цены с учетом количества.

add_action('woocommerce_before_calculate_totals', 'custom_change_price_based_on_quantity', 20, 1); 
function custom_change_price_based_on_quantity( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }

    // Чтобы не менять цену несколько раз при ajax
    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();

        // Пример: скидка 10% при покупке 3 и более штук
        if ( $quantity >= 3 ) {
            $new_price = $original_price * 0.9; // 10% скидка
        } else {
            $new_price = $original_price;
        }

        $cart_item['data']->set_price( $new_price );
    }
}

Что делает код

  • Проверяет, что скрипт не выполняется в админке без AJAX.
  • Предотвращает многократное срабатывание хука.
  • Перебирает все товары в корзине.
  • Если количество товара 3 или больше, устанавливает новую цену со скидкой 10%.
  • Иначе возвращает исходную цену.

Проверка результата после внедрения

1. Добавьте товар в корзину в количестве 1 и убедитесь, что цена не изменена.

2. Измените количество на 3 или больше на странице корзины. Обновите страницу и проверьте, что цена товара уменьшилась на 10%.

3. Проверьте, что суммарная стоимость корзины пересчиталась корректно.

4. Проверьте работу на фронтенде и при оформлении заказа, чтобы данные передавались корректно в заказ.

Частые ошибки и как их исправить

  • Цена меняется несколько раз: Используйте проверку did_action('woocommerce_before_calculate_totals'), чтобы избежать повторной установки цены.
  • Изменения не отображаются на странице корзины: Возможно, кэширование страницы или AJAX не обновляет стоимость. Очистите кэш и проверьте консоль браузера на ошибки.
  • Цена не сохраняется в заказе: Убедитесь, что цена изменяется именно в объекте товара корзины через $cart_item['data']->set_price(). Это сохранит цену в заказе.
  • Конфликты с другими плагинами скидок: Проверьте последовательность вызова хуков, возможно, ваш код должен иметь приоритет выше или ниже других функций.

Практические советы по безопасности и производительности

  • Не используйте тяжелые запросы к базе данных внутри хука woocommerce_before_calculate_totals, так как он вызывается часто.
  • Кэшируйте результаты вычислений, если формула сложная.
  • Проверяйте, что цена всегда положительная и корректная, чтобы избежать ошибок оформления заказа.
  • Перед публикацией протестируйте на staging-сайте, чтобы избежать сбоев в рабочем магазине.

Сравнение вариантов реализации

СпособПреимуществаНедостатки
Использование хука woocommerce_before_calculate_totalsГибко изменяет цену на лету, сохраняет цену в заказе, не требует плагиновТребует аккуратного кода, возможны конфликты с другими скидками
Плагин для скидок и правил ценообразованияГотовые решения с UI, поддержка разных сценариевПлатные, могут замедлять сайт, ограниченная кастомизация
Изменение цены товара в базе данныхПостоянное изменение ценыНебезопасно, влияет на все заказы, не подходит для динамических скидок

Сервис определения шаблона и плагинов на сайте