WooCommerce: как программно изменить стоимость товара в корзине по атрибутам

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

В WooCommerce стандартно стоимость товара определяется базовой ценой и вариациями. Но часто требуется реализовать дополнительное изменение цены в корзине в зависимости от выбранных атрибутов, которые не являются вариациями. Например, добавление наценки за особые параметры товара или скидки при определённых комбинациях.

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

Как проверить, что стоимость товара зависит от атрибутов

  • В карточке товара атрибуты отображаются, но не используются как вариации.
  • При добавлении товара в корзину цена не меняется автоматически.
  • Нужно, чтобы цена в корзине корректировалась программно после добавления товара.

Пошаговое решение: изменение цены товара в корзине по атрибутам через хук woocommerce_before_calculate_totals

Для решения задачи используем хук woocommerce_before_calculate_totals, который вызывается перед подсчётом итоговой суммы корзины. В этом хуке мы можем перебрать все товары в корзине и программно изменить цену в зависимости от нужных атрибутов.

1. Получаем товар и его атрибуты

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

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product = $cart_item['data'];
        $attributes = $product->get_attributes();
        // Продолжим в следующем шаге
    }
}

2. Проверяем нужные атрибуты и меняем цену

Предположим, у товара есть атрибут pa_color (цвет) и мы хотим добавить наценку +500 рублей, если выбран цвет «красный».

foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
    $product = $cart_item['data'];
    $variation_attributes = isset($cart_item['variation']) ? $cart_item['variation'] : [];

    if ( isset($variation_attributes['attribute_pa_color']) && $variation_attributes['attribute_pa_color'] === 'red' ) {
        $price = $product->get_price();
        $new_price = $price + 500;
        $product->set_price( $new_price );
    }
}

3. Полный рабочий пример кода

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

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product = $cart_item['data'];
        $variation_attributes = isset($cart_item['variation']) ? $cart_item['variation'] : [];

        // Добавляем наценку за красный цвет
        if ( isset($variation_attributes['attribute_pa_color']) && $variation_attributes['attribute_pa_color'] === 'red' ) {
            $price = $product->get_price();
            $new_price = $price + 500;
            $product->set_price( $new_price );
        }

        // Пример: скидка 200 рублей, если выбран атрибут размер L
        if ( isset($variation_attributes['attribute_pa_size']) && $variation_attributes['attribute_pa_size'] === 'l' ) {
            $price = $product->get_price();
            $new_price = max($price - 200, 0);
            $product->set_price( $new_price );
        }
    }
}

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

  1. Добавьте товар с нужными атрибутами в корзину.
  2. Перейдите в корзину и проверьте цену товара — она должна измениться согласно логике из кода.
  3. Проверьте несколько вариантов атрибутов для подтверждения корректной работы.
  4. Убедитесь, что итоговая сумма заказа корректна и отражает изменения.

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

  • Цена не меняется в корзине: проверьте, что хук подключён с правильным приоритетом и что $product->set_price() вызывается на объекте товара, а не на ID.
  • Изменения цены сохраняются для всех товаров: убедитесь, что логика изменения цены привязана к конкретным атрибутам, иначе цена изменится у всех товаров.
  • Цена сбрасывается при обновлении страницы: используйте хук woocommerce_before_calculate_totals именно с параметром 1 для аргументов, чтобы цена корректно пересчитывалась каждый раз.
  • Наценка/скидка применяется неправильно: внимательно проверьте ключи атрибутов — они должны начинаться с attribute_pa_ и соответствовать slug атрибута.

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

  • Не храните изменённые цены в пользовательских метаполях или базе — меняйте цену только в объекте $product в момент расчёта корзины.
  • Не усложняйте логику большого количества условий в одном хуке — выносите функции в отдельные методы для удобства поддержки.
  • Тестируйте изменения на локальной копии сайта, чтобы избежать сбоев на живом ресурсе.

Сравнение вариантов изменения цены по атрибутам

СпособПлюсыМинусыПрименимость
Создание вариаций с ценамиСтандартный метод, поддерживается WooCommerceМного вариаций, сложность управленияДля ограниченного набора вариантов
Код на хуке woocommerce_before_calculate_totalsГибкость, можно менять цену динамическиТребует навыков программированияДля кастомных условий
Плагины для наценок/скидокПростота использованияДоп. нагрузка, не всегда гибкоДля быстрых решений без кода

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