Проблема: как динамически изменять цену товара в 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, поддержка на владельце сайта |