WooCommerce: автоматическое изменение стоимости товара при изменении атрибутов с поддержкой вариантов

Диагностика проблемы: почему стандартный WooCommerce не меняет цену при выборе атрибутов

В WooCommerce стандартное поведение для переменных товаров — это автоматическое отображение цены варианта, выбранного пользователем. Однако при кастомной логике цены, например, если цена зависит от набора атрибутов или нужно динамически прибавлять/вычитать стоимость по отдельным атрибутам, стандартный функционал не подходит. В таких случаях цена не меняется или меняется некорректно.

Пользователи сталкиваются с задачей: автоматически пересчитывать стоимость товара при выборе комбинации атрибутов (варианта) с возможностью кастомных правил.

Как проверить текущую ситуацию

  • Создайте переменный товар с атрибутами и вариантами.
  • Перейдите на страницу товара на фронтенде.
  • Выберите разные комбинации атрибутов и посмотрите, меняется ли цена или остается статической.
  • Если цена не меняется или не соответствует правилам, требуются доработки.

Пошаговое решение: добавление динамического пересчёта цены на основе атрибутов

1. Используем хуки WooCommerce для изменения цены варианта

Для динамического изменения цены при выборе варианта можно использовать фильтр woocommerce_get_price_html для отображения цены и woocommerce_product_get_price для фактической цены продукта.

2. Пример кода для добавления дополнительной стоимости в зависимости от выбранных атрибутов

add_filter('woocommerce_product_get_price', 'custom_dynamic_price_based_on_attributes', 10, 2);
function custom_dynamic_price_based_on_attributes($price, $product) {
    if (!$product->is_type('variable')) {
        return $price;
    }

    // Получаем выбранные атрибуты из запроса
    if (!isset($_REQUEST['attribute_pa_color']) && !isset($_REQUEST['attribute_pa_size'])) {
        return $price; // Если атрибуты не выбраны, возвращаем базовую цену варианта
    }

    $extra = 0;

    // Добавляем стоимость за цвет
    if (!empty($_REQUEST['attribute_pa_color'])) {
        $color = sanitize_text_field($_REQUEST['attribute_pa_color']);
        if ($color === 'red') {
            $extra += 10; // красный цвет +10 рублей
        } elseif ($color === 'blue') {
            $extra += 5;
        }
    }

    // Добавляем стоимость за размер
    if (!empty($_REQUEST['attribute_pa_size'])) {
        $size = sanitize_text_field($_REQUEST['attribute_pa_size']);
        if ($size === 'large') {
            $extra += 20;
        } elseif ($size === 'medium') {
            $extra += 10;
        }
    }

    return $price + $extra;
}

3. Обновление цены на фронтенде с помощью JavaScript

WooCommerce по умолчанию не обновит цену автоматически, если мы меняем логику PHP. Нужно добавить простой jQuery-скрипт, который при изменении выбора атрибутов обновит блок с ценой.

jQuery(function($) {
    $('form.variations_form').on('woocommerce_variation_select_change', function() {
        var form = $(this);
        var data = form.serialize();

        $.ajax({
            url: wc_add_to_cart_params.ajax_url,
            method: 'POST',
            data: {
                action: 'get_dynamic_price',
                data: data,
                product_id: form.data('product_id')
            },
            success: function(response) {
                if (response.price_html) {
                    form.find('.woocommerce-variation-price').html(response.price_html);
                }
            }
        });
    });
});

4. Серверная часть для AJAX-обработки

add_action('wp_ajax_get_dynamic_price', 'ajax_get_dynamic_price');
add_action('wp_ajax_nopriv_get_dynamic_price', 'ajax_get_dynamic_price');

function ajax_get_dynamic_price() {
    parse_str($_POST['data'], $attributes);

    $product_id = intval($_POST['product_id']);
    $product = wc_get_product($product_id);

    if (!$product || !$product->is_type('variable')) {
        wp_send_json_error();
        wp_die();
    }

    $variation_id = 0;
    $variations = $product->get_available_variations();

    foreach ($variations as $variation) {
        $match = true;
        foreach ($attributes as $key => $value) {
            if (strpos($key, 'attribute_') === 0) {
                $attr_name = str_replace('attribute_', '', $key);
                if (!isset($variation['attributes']['attribute_' . $attr_name]) || $variation['attributes']['attribute_' . $attr_name] !== $value) {
                    $match = false;
                    break;
                }
            }
        }
        if ($match) {
            $variation_id = $variation['variation_id'];
            break;
        }
    }

    if ($variation_id === 0) {
        wp_send_json_error();
        wp_die();
    }

    $variation = wc_get_product($variation_id);
    $base_price = $variation->get_price();

    // Ваша логика добавления дополнительной стоимости
    $extra = 0;
    if (!empty($attributes['attribute_pa_color'])) {
        if ($attributes['attribute_pa_color'] === 'red') {
            $extra += 10;
        } elseif ($attributes['attribute_pa_color'] === 'blue') {
            $extra += 5;
        }
    }
    if (!empty($attributes['attribute_pa_size'])) {
        if ($attributes['attribute_pa_size'] === 'large') {
            $extra += 20;
        } elseif ($attributes['attribute_pa_size'] === 'medium') {
            $extra += 10;
        }
    }

    $final_price = $base_price + $extra;
    $price_html = wc_price($final_price);

    wp_send_json_success(['price_html' => $price_html]);
    wp_die();
}

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

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

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

  • Цена не обновляется на фронтенде: не подключен или неправильно работает JS-скрипт. Проверьте консоль браузера на ошибки и правильность селекторов.
  • AJAX-запросы возвращают ошибку: не зарегистрированы AJAX-обработчики или неверно передаются данные. Проверьте хуки wp_ajax_ и формат запроса.
  • Некорректное сопоставление варианта: убедитесь, что имена атрибутов и значения совпадают с тем, что хранится в WooCommerce (например, pa_color, а не просто color).
  • Цена не учитывает дополнительные параметры: проверьте логику прибавления стоимости в PHP-функциях, убедитесь в правильности условий.

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

  • Сохраняйте и кешируйте результаты вычисления цены, если сложная логика — чтобы не нагружать сервер на каждом AJAX-запросе.
  • Обязательно фильтруйте входящие данные через sanitize_text_field или подобные функции для безопасности.
  • Используйте nonce для AJAX-запросов, чтобы избежать CSRF-атак.
  • Минимизируйте количество AJAX-запросов, объединяя логику или добавляя debounce на выбор атрибутов.
  • Для крупных магазинов рассмотрите использование встроенного кэширования WooCommerce и CDN для статических ресурсов.

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

ВариантПлюсыМинусы
Стандартное поведение WooCommerceПростота, автоматическое обновление, поддержка вариацийНет кастомной логики изменения цены по атрибутам
Изменение цены через PHP фильтры + AJAXГибкость, поддержка любых правил, динамическое обновлениеТребует написания кода, возможные ошибки в JS и PHP
Использование плагинов для динамических ценГотовые решения, поддержка без кодаСтоимость, ограниченная кастомизация, нагрузка на сайт
Как избежать конфликтов между плагинами WordPress: практическое руководство
03.04.2026
Как изменить авторские права в футере WordPress
30.03.2026
Автоматическое удаление старых transient в WordPress: практическое руководство
19.03.2026
Как проверить и исправить ошибки базы данных WordPress
25.01.2026
Как автоматизировать создание и удаление категорий в WordPress программно
11.03.2026