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

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

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

Проверить проблему можно так:

  • Откройте страницу товара с вариациями.
  • Измените атрибуты вариации и посмотрите, меняется ли цена автоматически.
  • Если цена не меняется, значит, стандартного обновления недостаточно.

Пошаговое решение: динамическое обновление цены через AJAX

1. Подключение скрипта для отслеживания изменений атрибутов

Добавим JavaScript, который будет ловить выбор вариаций и запрашивать обновленную цену через AJAX.

add_action('wp_enqueue_scripts', function() {
    if (is_product()) {
        wp_enqueue_script('custom-variation-price-update', get_stylesheet_directory_uri() . '/js/variation-price-update.js', ['jquery'], '1.0', true);
        wp_localize_script('custom-variation-price-update', 'ajaxParams', [
            'ajax_url' => admin_url('admin-ajax.php'),
            'product_id' => get_the_ID(),
            'nonce' => wp_create_nonce('variation_price_nonce')
        ]);
    }
});

2. Создание AJAX-обработчика на сервере

В functions.php добавим обработчик, который получит выбранные атрибуты, определит вариацию и вернет цену.

add_action('wp_ajax_get_variation_price', 'get_variation_price_callback');
add_action('wp_ajax_nopriv_get_variation_price', 'get_variation_price_callback');

function get_variation_price_callback() {
    check_ajax_referer('variation_price_nonce', 'nonce');

    $product_id = intval($_POST['product_id']);
    $attributes = $_POST['attributes'] ?? [];

    if (!$product_id || empty($attributes)) {
        wp_send_json_error('Неверные данные');
    }

    $product = wc_get_product($product_id);
    if (!$product || !$product->is_type('variable')) {
        wp_send_json_error('Товар не вариативный');
    }

    $available_variations = $product->get_available_variations();
    foreach ($available_variations as $variation) {
        $match = true;
        foreach ($attributes as $attr_name => $attr_value) {
            if (!isset($variation['attributes']['attribute_' . $attr_name]) || $variation['attributes']['attribute_' . $attr_name] !== $attr_value) {
                $match = false;
                break;
            }
        }
        if ($match) {
            $variation_obj = wc_get_product($variation['variation_id']);
            $price_html = $variation_obj->get_price_html();
            wp_send_json_success(['price_html' => $price_html]);
        }
    }

    wp_send_json_error('Вариация не найдена');
}

3. Скрипт для фронтенда: отправка данных и обновление цены

jQuery(document).ready(function($) {
    $('.variations_form').on('change', 'select', function() {
        let attributes = {};
        $('.variations_form select').each(function() {
            let attrName = $(this).attr('name').replace('attribute_', '');
            let attrValue = $(this).val();
            if (attrValue) {
                attributes[attrName] = attrValue;
            }
        });

        if (Object.keys(attributes).length === 0) {
            return;
        }

        $.ajax({
            url: ajaxParams.ajax_url,
            method: 'POST',
            data: {
                action: 'get_variation_price',
                nonce: ajaxParams.nonce,
                product_id: ajaxParams.product_id,
                attributes: attributes
            },
            success: function(response) {
                if (response.success) {
                    $('.woocommerce-variation-price').html(response.data.price_html);
                }
            },
            error: function() {
                console.log('Ошибка при получении цены вариации');
            }
        });
    });
});

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

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

  • Очистите кеш браузера и сайта.
  • Откройте страницу вариативного товара.
  • Выберите различные атрибуты вариаций.
  • Убедитесь, что цена обновляется мгновенно без перезагрузки.
  • Если цена не меняется — проверьте консоль браузера на наличие ошибок JS и логи PHP.

Частые ошибки и пути их исправления

  • Несоответствие названий атрибутов: В AJAX-запросе и PHP атрибуты должны совпадать по имени, включая префикс attribute_.
  • Отсутствует nonce или он не совпадает: Проверьте, что nonce передается и проверяется правильно в обработчике.
  • JavaScript не загружается: Убедитесь, что скрипт подключается только на страницах товара и путь к файлу верный.
  • Кэширование страницы: Некоторые плагины кэширования могут блокировать динамическое обновление. Временно отключите кэш или настройте исключения.

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

  • Используйте wp_localize_script для передачи данных AJAX, чтобы избежать хардкода URL и nonce в JS.
  • Проверяйте nonce в обработчике, чтобы предотвратить CSRF-атаки.
  • Минимизируйте количество вызовов AJAX, добавляя задержку или отправляя запрос только после выбора всех атрибутов.
  • Если сайт сильно нагружен, рассмотрите кэширование результатов AJAX на стороне сервера.

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

КритерийИспользование плагинаКастомный код
ГибкостьОграничена функционалом плагинаПолный контроль над логикой и отображением
ПроизводительностьМожет быть перегружен лишним кодомОптимизирован под конкретные задачи
БезопасностьЗависит от автора плагинаЗависит от качества кода разработчика
ОбновленияАвтоматические через WPТребует ручного сопровождения
Сложность внедренияМинимальнаяТребует знаний PHP и JS
Как добавить автоматическое обновление тем и плагинов в WordPress
15.04.2026
Автоматизация заливки данных в WordPress через REST API: практическое руководство
15.12.2025
Как создать автоматический импорт событий в WordPress через REST API
11.04.2026
Как создать динамический фильтр по мета-полям в WordPress с примером кода
28.01.2026
Как защитить WordPress от Brute Force атак
26.12.2025