Обзор задачи: зачем менять стоимость товаров программно
В WooCommerce часто возникает необходимость менять цену товара динамически — например, в зависимости от даты, пользовательской роли или акций. Вместо ручного редактирования цен полезно использовать хуки WordPress и WooCommerce для автоматизации процесса. В статье разберём, как именно реализовать автоматическое изменение стоимости товара через хуки, приведём рабочие примеры и расскажем, как проверить результат.
Диагностика проблемы: почему не работает изменение цены
Если вы пробовали менять цену товара через хуки, но изменения не применяются, проверьте следующие моменты:
- Правильно ли выбран хук для изменения цены (например,
woocommerce_before_calculate_totalsдля изменения цены в корзине)? - Изменяете ли вы цену объекта товара, а не просто переменную?
- Не конфликтует ли ваш код с другими плагинами, которые могут перезаписывать цену?
- Вы не изменяете цену товара в базе, а только для сессии пользователя?
Пошаговое решение: изменение цены в корзине с помощью хука
Рассмотрим пример, когда нужно автоматически снизить цену на 10% для пользователей с ролью wholesale_customer.
1. Подключаемся к хуку woocommerce_before_calculate_totals
Этот хук срабатывает при пересчёте стоимости товаров в корзине. В нём можно изменить цену каждого товара.
2. Проверяем роль пользователя и корректируем цену
add_action('woocommerce_before_calculate_totals', 'custom_wholesale_discount', 10, 1);
function custom_wholesale_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// Проверяем роль
$user = wp_get_current_user();
if (!in_array('wholesale_customer', (array) $user->roles)) {
return;
}
// Проходим по товарам в корзине
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$original_price = $product->get_regular_price();
$discounted_price = $original_price * 0.9; // скидка 10%
$product->set_price($discounted_price);
}
}3. Добавляем проверку, чтобы не применялось в админке и AJAX-запросах
Это нужно, чтобы не ломать обработку в панели управления и при обновлении корзины.
Проверка результата после внедрения
После добавления кода:
- Залогиньтесь под пользователем с ролью
wholesale_customer. - Добавьте товар в корзину.
- В корзине цена должна автоматически уменьшиться на 10%.
- Под другим пользователем цена останется без изменений.
Для дополнительной проверки можно временно вставить error_log() внутри функции и смотреть логи сервера, например:
error_log('Original price: ' . $original_price . ', Discounted price: ' . $discounted_price);Частые ошибки и как их исправить
- Изменение цены не отображается: Возможно, вы меняете цену не у объекта
$product, а у массива. Используйте$product->set_price(). - Цена меняется глобально для всех пользователей: Проверьте условие по роли пользователя. Возможно, роль не передается корректно.
- Код ломает админку: Добавьте проверку
is_admin() && !defined('DOING_AJAX')и пропускайте выполнение в админке. - Кэширование мешает обновлению цены: Очистите кэш плагинов или серверный кэш.
Практические советы по безопасности и производительности
- Не сохраняйте изменённую цену в базу, если это временная скидка — меняйте только в объекте товара для текущего сеанса.
- Используйте точечные условия для запуска кода, чтобы не влиять на всю нагрузку сайта.
- Тестируйте функцию на staging-сервере перед запуском на живом сайте.
- Если работаете с большими корзинами, оптимизируйте цикл, избегайте повторных вызовов методов.
Дополнительно: сравнение вариантов реализации
| Вариант | Пример | Плюсы | Минусы |
|---|---|---|---|
Изменение цены через woocommerce_before_calculate_totals | Код выше | Гибко, без изменения базы, работает для корзины | Не меняет цену в каталоге, только в корзине |
Использование фильтра woocommerce_get_price | | Меняет цену везде, включая каталог | Может конфликтовать с другими плагинами и кешем |
| Изменение цены напрямую в базе | SQL-запросы к таблице wp_postmeta | Постоянное изменение цены | Риск ошибок, нужно откатить изменения вручную |