Диагностика задачи: зачем нужна автоматическая корректировка цен при накопительных скидках
Во многих интернет-магазинах на WooCommerce реализована система накопительных скидок, при которой цена товара меняется в зависимости от общей суммы покупок клиента или количества заказанных товаров. Стандартный функционал WooCommerce не позволяет автоматически изменять стоимость товаров в зависимости от предыдущих покупок или текущей корзины. Это часто приводит к необходимости ручного редактирования цен или использования громоздких плагинов, которые могут замедлять сайт.
Задача: настроить автоматическую корректировку цены товара с учетом накопленных скидок с помощью собственного кода, минимизируя влияние на производительность и сохраняя совместимость с обновлениями WooCommerce.
Шаги решения: автоматическое изменение цены товара через хуки WooCommerce
1. Выбор хука для изменения цены
Для динамической корректировки цены в WooCommerce оптимально использовать фильтр woocommerce_product_get_price и woocommerce_product_get_regular_price. Они позволяют перехватить вызов цены товара и заменить ее на свое значение без изменения самой записи в базе данных.
2. Пример кода изменения цены с учетом накопительной скидки
Ниже простой пример, который снижает цену товара на 5% при достижении в мета-поле пользователя суммы покупок свыше 10000 рублей. В реальном проекте расчет суммы покупок можно заменить на более сложную логику.
add_filter('woocommerce_product_get_price', 'apply_cumulative_discount_to_price', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'apply_cumulative_discount_to_price', 10, 2);
function apply_cumulative_discount_to_price($price, $product) {
// Получаем ID текущего пользователя
$user_id = get_current_user_id();
if (!$user_id) {
return $price; // если гость, цена без изменений
}
// Получаем сумму покупок из пользовательского мета (пример)
$total_spent = (float) get_user_meta($user_id, '_total_spent', true);
if ($total_spent >= 10000) {
// Применяем скидку 5%
$price = $price * 0.95;
}
return round($price, 2);
}3. Автоматическое обновление мета-поля с суммой покупок
Для автоматизации необходимо обновлять _total_spent после каждого завершенного заказа. Используем хук woocommerce_order_status_completed:
add_action('woocommerce_order_status_completed', 'update_user_total_spent');
function update_user_total_spent($order_id) {
$order = wc_get_order($order_id);
$user_id = $order->get_user_id();
if (!$user_id) {
return;
}
$total_spent = (float) get_user_meta($user_id, '_total_spent', true);
$order_total = (float) $order->get_total();
$new_total = $total_spent + $order_total;
update_user_meta($user_id, '_total_spent', $new_total);
}Проверка результата после внедрения
- Залогиньтесь под пользователем с общей суммой покупок больше 10000 (или вручную установите мета
_total_spentчерез phpMyAdmin или WP-CLI). - Перейдите на страницу товара и убедитесь, что цена уменьшена на 5%.
- Оформите новый заказ и после подтверждения статуса «Завершён» проверьте увеличение мета-поля
_total_spentи корректное обновление цены при следующем посещении.
Частые ошибки при реализации и как их исправить
- Цена не меняется: убедитесь, что используете правильные хуки
woocommerce_product_get_priceиwoocommerce_product_get_regular_price, а не другие фильтры. - Скидка не применяется для гостей: это нормальное поведение, т.к. нет user ID. Для гостей можно добавить отдельную логику, если необходимо.
- Цена сбрасывается на старую при кешировании: отключите кеширование страниц для пользователей с накопительными скидками (например, через настройки плагина кеша или с помощью
DONOTCACHEPAGE). - Некорректная сумма покупок: проверьте логику обновления
_total_spent, чтобы учитывать только завершённые заказы и избегать дублирования.
Практические советы по безопасности и производительности
- Поддерживайте логику обновления мета-поля только на статусе
completed, чтобы не суммировать отменённые и возвратные заказы. - Используйте
round()для округления цен, чтобы избежать дробных значений с длинной десятичной частью. - Кешируйте результат подсчета суммы покупок, если вычисления усложняются, например, через транзиенты.
- Проверяйте совместимость с плагинами кеширования, отключая кеш для динамических страниц с ценами.
- Не храните чувствительную информацию в пользовательских мета без шифрования — в данном случае это безопасно, так как это только сумма.
Сравнение подходов: плагин vs. кастомный код
| Критерий | Плагин накопительных скидок | Кастомный код (описанный выше) |
|---|---|---|
| Гибкость | Ограничена функционалом плагина | Полный контроль, можно адаптировать под любые правила |
| Производительность | Может замедлять сайт из-за лишних запросов | Минимальное влияние при оптимизации |
| Обновляемость | Обновляется автоматически, но может конфликтовать | Требует поддержки разработчиком |
| Стоимость | Часто платные | Бесплатно, если реализовать самостоятельно |
| Сложность внедрения | Простая установка | Требуется знания PHP и WooCommerce API |