WooCommerce: автоматическое изменение цены при смене атрибутов товара

Проблема: как динамически изменять цену товара в WooCommerce при выборе атрибутов

В стандартном WooCommerce цена товара не меняется автоматически при выборе определённых атрибутов (например, цвет, размер), если не используются вариации (variable products). Однако, когда у вас простой товар с атрибутами и требуется динамическая корректировка цены без создания вариаций, стандартного решения нет. Это часто встречается при продаже товаров с доплатами за опции.

Диагностика проблемы

  • Проверьте, что товар в WooCommerce — простой (simple product), а не вариативный.
  • Убедитесь, что атрибуты добавлены к товару и видны на странице.
  • Проверьте, что цена товара установлена и не меняется при выборе атрибутов на фронте.
  • Проверьте, что не используются плагины для вариаций или кастомных опций, которые могут конфликтовать.

Как реализовать автоматическое изменение цены с помощью JavaScript и PHP

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

1. Добавляем дополнительные цены для атрибутов в метаполе товара

В админке можно хранить данные, например, в виде:

$additional_prices = [
  'color_red' => 200,  // +200 руб.
  'color_blue' => 100,
  'size_large' => 300
];

Для простоты создадим массив в коде. Для продвинутого решения можно добавить поля в админке товара.

2. Добавляем скрипт для динамического изменения цены на странице товара

add_action('wp_enqueue_scripts', function() {
    if (is_product()) {
        wp_enqueue_script('custom-price-update', get_stylesheet_directory_uri() . '/js/custom-price-update.js', ['jquery'], false, true);
        // Передаем данные с доп.ценами в JS
        wp_localize_script('custom-price-update', 'additionalPrices', [
            'color_red' => 200,
            'color_blue' => 100,
            'size_large' => 300
        ]);
    }
});

В файле custom-price-update.js пишем:

jQuery(function($) {
    const basePrice = parseFloat($('.woocommerce-Price-amount').first().text().replace(/[^\d\.]/g, '')) || 0;

    function updatePrice() {
        let extra = 0;
        $('select[name^="attribute_"]').each(function() {
            const val = $(this).val();
            if (val && additionalPrices[val]) {
                extra += additionalPrices[val];
            }
        });
        const newPrice = basePrice + extra;
        $('.woocommerce-Price-amount').first().text(newPrice.toLocaleString('ru-RU', {style: 'currency', currency: 'RUB'}));
    }

    $('select[name^="attribute_"]').on('change', updatePrice);
});

3. Обновляем цену при добавлении товара в корзину

Чтобы цена учитывалась в корзине, нужно изменить цену товара при добавлении, используя хук woocommerce_before_calculate_totals:

add_action('woocommerce_before_calculate_totals', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    foreach ($cart->get_cart() as $cart_item) {
        $product = $cart_item['data'];
        $base_price = $product->get_price();
        $extra = 0;
        if (!empty($cart_item['variation_attributes'])) {
            foreach ($cart_item['variation_attributes'] as $attr) {
                if (!empty($attr) && isset($additional_prices[$attr])) {
                    $extra += $additional_prices[$attr];
                }
            }
        } elseif (!empty($cart_item['attributes'])) {
            foreach ($cart_item['attributes'] as $attr) {
                if (!empty($attr) && isset($additional_prices[$attr])) {
                    $extra += $additional_prices[$attr];
                }
            }
        }
        $cart_item['data']->set_price($base_price + $extra);
    }
});

Обратите внимание: $additional_prices нужно объявить глобально или подключать из настроек.

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

  • Откройте страницу товара с добавленным кодом.
  • Выберите различные атрибуты (цвет, размер) и посмотрите, как меняется цена на странице без перезагрузки.
  • Добавьте товар в корзину и перейдите в корзину — цена должна учитывать выбранные опции.
  • Оформите заказ, чтобы убедиться, что цена передаётся корректно.

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

  • Цена не меняется на странице товара
    Проверьте, что селекторы в JS соответствуют структуре темы. Для кастомных тем селекторы могут отличаться.
  • Цена в корзине не учитывает опции
    Проверьте, что хук woocommerce_before_calculate_totals добавлен и работает; убедитесь, что данные опций передаются в $cart_item.
  • Ошибки JS в консоли
    Проверьте правильность локализации скрипта и наличие jQuery на странице.
  • Данные доп.цен не сохраняются
    Если доп.цены определяются в админке, проверьте сохранение и получение метаданных товара.

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

  • Не храните цены доплат в открытом JS — используйте wp_localize_script для передачи только нужных данных.
  • Кэшируйте данные доплат для быстрого доступа, например, с помощью транзиентов, если они вычисляются динамически.
  • Проверяйте и валидируйте данные с фронтенда на сервере, чтобы предотвратить манипуляции с ценами.
  • Минимизируйте влияние на производительность, не добавляйте сложных вычислений в циклы корзины.

Сравнение подходов: плагины vs кастомный код

ПодходПлюсыМинусы
Плагины для дополнительных опций (например, WooCommerce Product Add-Ons)Готовый функционал, поддержка, настройка без кодаСтоят денег, могут замедлять сайт, не всегда гибко
Кастомный код (описанный выше)Максимальная гибкость, легковесность, точное решениеТребует навыков PHP/JS, поддержка на владельце сайта
WooCommerce: как исправить проблемы с изменением цены при выборе вариаций товара
22.05.2026
Как отправлять JSON данные из WordPress внешним сервисам
14.04.2026
WooCommerce: невозможно изменить складские запасы через админку — как исправить
17.04.2026
Как автоматизировать создание и удаление черновиков в WordPress
26.03.2026
WooCommerce: невозможно изменить складские запасы через админку — как исправить
17.04.2026