Диагностика задачи: зачем менять стоимость товара программно
В стандартном WooCommerce цена товара задаётся в карточке и меняется вручную или через вариации. Однако в ряде случаев требуется динамически изменять цену при добавлении в корзину, например, при определённых условиях: пользователь из определённой роли, количество товаров, или наличие определённых товаров в корзине. Это невозможно реализовать без кода или специализированных плагинов.
Часто владельцы сталкиваются с тем, что попытки изменить цену не работают — причина в том, что цена товара в WooCommerce берётся из объекта продукта, и простое изменение $_POST или JavaScript не срабатывает на сервере.
Пошаговое решение: изменение цены товара в корзине через хук woocommerce_before_calculate_totals
Правильный способ — использовать фильтр, который срабатывает перед подсчётом итоговой стоимости корзины. Ниже пример, как изменить цену продукта в корзине, если пользователь — подписчик, и добавлено больше 3 единиц товара.
add_action('woocommerce_before_calculate_totals', 'custom_dynamic_price_change', 20, 1);
function custom_dynamic_price_change( $cart ) {
if ( is_admin() && ! defined('DOING_AJAX') ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Проверяем роль пользователя
if ( ! is_user_logged_in() ) return;
$user = wp_get_current_user();
if ( ! in_array( 'subscriber', (array) $user->roles ) ) return;
foreach ( $cart->get_cart() as $cart_item ) {
$quantity = $cart_item['quantity'];
// Если количество больше 3, уменьшаем цену на 10%
if ( $quantity > 3 ) {
$original_price = $cart_item['data']->get_regular_price();
$new_price = $original_price * 0.9; // скидка 10%
$cart_item['data']->set_price( $new_price );
}
}
}
Этот код нужно добавить в файл functions.php вашей дочерней темы или в плагин для кастомных функций.
Как адаптировать под другие условия
- Замените проверку роли пользователя на другую, например,
administratorили кастомную роль. - Меняйте цену в зависимости от ID товара, проверяя
$cart_item['product_id']. - Добавляйте дополнительные условия, например, проверку текущей даты или наличия промокода.
Проверка результата после внедрения
Чтобы проверить работоспособность:
- Авторизуйтесь под пользователем с ролью
subscriberили нужной ролью. - Добавьте в корзину более 3 единиц одного и того же товара.
- Перейдите в корзину, проверьте цену товара — должна быть уменьшена на 10% от базовой цены.
- Попробуйте добавить меньше 4 единиц — цена не изменится.
- Авторизуйтесь под пользователем без нужной роли — цена не должна меняться.
Для отладки можно временно добавить error_log в функцию, например:
error_log('Цена изменена для товара ID '.$cart_item['product_id']);
Частые ошибки и как исправить
- Изменение цены не работает: вероятно, код не подключен или происходит раньше, чем рассчитывается корзина. Убедитесь, что хук
woocommerce_before_calculate_totalsиспользуется с приоритетом 20 или выше. - Цена меняется для всех пользователей: проверьте условие на роль пользователя, возможно, пользователь не авторизован или роль указана неверно.
- Изменённая цена сбрасывается после обновления страницы: убедитесь, что код работает при каждом пересчёте корзины, не сохраняйте цену в базе.
- Конфликты с плагинами кеширования: кеширование страниц может мешать динамическим изменениям цен. Используйте исключения для страниц корзины и оформления заказа.
Практические советы по производительности и безопасности
- Не изменяйте цену товара напрямую в базе — это должно происходить только в объекте корзины.
- Избегайте тяжёлых запросов в функции изменения цены — кешируйте данные, если нужны сложные проверки.
- Проверяйте, что код не выполняется в административной панели, чтобы не влиять на админские операции.
- Если используете сторонние плагины для скидок, убедитесь в совместимости с вашим кодом.
Сравнение способов динамического изменения цены в WooCommerce
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
Хук woocommerce_before_calculate_totals | Гибкость, точечное изменение цены в корзине | Требует навыков PHP, не работает вне корзины | Пример из статьи |
| Плагины скидок (например, WooCommerce Dynamic Pricing) | Простота настройки, готовые правила | Может быть дорого, ограничена кастомизация | Официальный плагин |
| JavaScript на фронтенде | Быстрое изменение отображения цены | Не влияет на итоговую стоимость на сервере | Недопустимо для изменения цены |