Диагностика проблемы: зачем менять цены при обновлении атрибутов
В стандартном WooCommerce изменение атрибутов товара (например, размера или цвета) не влияет на цену автоматически. Часто владельцы магазинов сталкиваются с необходимостью менять цену или скидку товара при изменении определённого атрибута без ручного редактирования каждого варианта. Например, при выборе премиального материала цена должна расти, или при смене размера - меняться скидка.
Без автоматизации это требует постоянного ручного обновления, что неудобно и ошибочно. Поэтому задача — реализовать автоматическую корректировку цены и скидки товара в зависимости от выбранных или обновлённых атрибутов.
Как определить, что цена не обновляется корректно
- Вы изменяете атрибуты товара в админке или через импорт, но цена вариации остаётся прежней.
- При смене атрибута на фронтенде цена не меняется динамически (если это требуется).
- В панели заказов и на сайте отображаются старые цены, не учитывающие новые атрибуты.
Пошаговое решение: автоматическое изменение цены и скидок через хук сохранения вариации
Для решения задачи нам нужно отследить событие сохранения вариации и в зависимости от выбранных атрибутов скорректировать цену и скидку. Используем хук woocommerce_save_product_variation.
1. Подключаем функцию к хуку
add_action('woocommerce_save_product_variation', 'wpset_update_variation_price_on_attribute_change', 10, 2);2. Реализуем функцию изменения цены
function wpset_update_variation_price_on_attribute_change($variation_id, $i) {
$variation = wc_get_product($variation_id);
if (!$variation) {
return;
}
// Получаем атрибуты вариации
$attributes = $variation->get_attributes();
// Пример логики: если атрибут 'pa_material' равен 'premium', увеличиваем цену на 20%
if (isset($attributes['pa_material']) && $attributes['pa_material'] === 'premium') {
$regular_price = $variation->get_regular_price();
if ($regular_price) {
$new_price = $regular_price * 1.2; // +20%
$variation->set_price($new_price);
$variation->set_regular_price($new_price);
// Можно задать скидку, например, 10% от новой цены
$sale_price = $new_price * 0.9;
$variation->set_sale_price($sale_price);
}
} else {
// Если материал не premium, сбрасываем скидку и возвращаем базовую цену
// Предположим, базовая цена хранится в метаполе '_base_price'
$base_price = get_post_meta($variation_id, '_base_price', true);
if ($base_price) {
$variation->set_price($base_price);
$variation->set_regular_price($base_price);
$variation->set_sale_price('');
}
}
$variation->save();
}3. Сохраняем базовую цену при создании вариации
Чтобы иметь эталон цены, можно сохранить базовую цену при создании вариации или вручную добавить метаполе _base_price для уже созданных вариаций.
add_action('woocommerce_save_product_variation', 'wpset_save_base_price_variation', 20, 2);
function wpset_save_base_price_variation($variation_id, $i) {
$variation = wc_get_product($variation_id);
if ($variation && !get_post_meta($variation_id, '_base_price', true)) {
update_post_meta($variation_id, '_base_price', $variation->get_regular_price());
}
}Проверка результата после внедрения
- Создайте или отредактируйте вариацию, установив атрибут
pa_materialвpremium. - Сохраните вариацию и проверьте, что цена увеличилась на 20%, а скидка применена.
- Измените атрибут на другой и убедитесь, что цена вернулась к базовой и скидка снялась.
- Проверьте на фронтенде (если вариации доступны для выбора) — цена должна соответствовать логике.
Частые ошибки и причины с их устранением
- Ничего не меняется после сохранения вариации: проверьте, что вы используете правильный атрибут (с префиксом
pa_) и значение соответствует реально существующему в WooCommerce. - Цена не обновляется на фронтенде: убедитесь, что кэш очищен, а тема корректно выводит обновлённую цену вариации.
- Ошибка при сохранении вариации: проверьте права пользователя, а также правильность вызова
$variation->save()и отсутствие конфликтов с другими плагинами. - Скидка не применяется: убедитесь, что для вариации выставлена
sale_price, и она нижеregular_price.
Практические советы по безопасности и производительности
- Всегда проверяйте существование объекта продукта перед изменениями.
- Минимизируйте общее количество операций сохранения вариаций за одну сессию, чтобы не перегружать базу.
- Кэшируйте результаты, если применяете сложную логику вычисления цены.
- Используйте
wp_cache_delete()для очистки кэша WooCommerce при необходимости. - Тестируйте изменения на staging-среде, чтобы избежать сбоев в рабочем магазине.
Сравнение вариантов реализации автоматического изменения цены
| Метод | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
| Использование хуков (как в статье) | Гибко, не требует плагинов, легко кастомизировать | Требует навыков программирования, можно допустить ошибки | Для индивидуальных проектов с уникальной логикой |
| Плагины для управления вариациями и ценами | Простота настройки, поддержка, готовые функции | Может замедлять сайт, ограничены возможностями | Для быстрых решений без кода |
| Импорт и обновление через CSV с ценами | Удобно для массовых изменений | Менее динамично, требует повторного импорта | При массовом обновлении большого каталога |