Диагностика задачи: зачем менять стоимость товара после первого заказа
В WooCommerce иногда требуется автоматически изменять цену товара после того, как пользователь совершил первый заказ этого товара. Причины могут быть разные: стимулировать повторные покупки скидкой, ограничить акционные цены или реализовать динамическое ценообразование на основе истории клиента.
Стандартными средствами WooCommerce такой функционал не поддерживается. Необходимо использовать кастомный код с применением хуков WooCommerce и WordPress, чтобы определить первый заказ пользователя и изменить стоимость товара на лету.
Как определить первый заказ пользователя с товаром
Первый шаг — проверить, есть ли у текущего покупателя в базе заказ с конкретным товаром. Для этого используем класс WC_Order_Query и методы WooCommerce для получения истории заказов пользователя.
function user_has_ordered_product($user_id, $product_id) {
if (!$user_id) return false;
$orders = wc_get_orders(array(
'customer_id' => $user_id,
'limit' => -1,
'status' => array('wc-completed', 'wc-processing')
));
foreach ($orders as $order) {
foreach ($order->get_items() as $item) {
if ($item->get_product_id() == $product_id) {
return true;
}
}
}
return false;
}Пошаговое решение: изменение цены товара в корзине после первого заказа
Для изменения цены товара на лету используем хук woocommerce_before_calculate_totals. В этом хук мы будем проверять пользователя, товар и менять стоимость, если условие — первый заказ — выполнено.
add_action('woocommerce_before_calculate_totals', 'change_price_after_first_order', 20);
function change_price_after_first_order($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) return;
$user_id = get_current_user_id();
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product_id = $cart_item['product_id'];
if (user_has_ordered_product($user_id, $product_id)) {
// Пример: уменьшаем цену на 20% после первого заказа
$original_price = $cart_item['data']->get_regular_price();
$new_price = $original_price * 0.8;
$cart_item['data']->set_price($new_price);
}
}
}Проверка результата после внедрения
- Авторизуйтесь под пользователем, который уже покупал товар, и добавьте этот товар в корзину — цена должна измениться согласно логике.
- Авторизуйтесь под новым пользователем, который не делал заказов — цена останется оригинальной.
- Отладочные логи можно добавить через
error_log()для подтверждения вызовов функции. - Проверьте фронтенд страницы корзины и оформления заказа — цена должна отображаться корректно.
Частые ошибки и их исправление
- Цена не меняется: Проверьте приоритет хука, он должен быть ниже 20, чтобы переопределить цену до подсчёта корзины.
- Цена меняется для всех пользователей: Убедитесь, что функция
user_has_ordered_product()корректно проверяет историю заказов именно текущего пользователя. - Изменённая цена не сохраняется при переходе между страницами: Проверьте, нет ли конфликтов с кешированием корзины или сторонними плагинами.
- Проблемы с вариациями товаров: В случае вариативных товаров проверяйте ID вариации через
$item->get_variation_id()вместоproduct_id.
Практические советы по безопасности и производительности
- Кешируйте результаты проверки заказов для пользователя с помощью transient API, чтобы не выполнять тяжелые запросы при каждом обновлении корзины.
- Используйте только необходимые статусы заказов (например,
wc-completed) для проверки, чтобы избежать ложных срабатываний. - Обрабатывайте только фронтенд запросы, чтобы не нагружать админку.
Чек-лист для внедрения автоматического изменения цены после первого заказа
- Реализовать функцию проверки наличия первого заказа с товаром у пользователя.
- Использовать хук
woocommerce_before_calculate_totalsдля изменения цены в корзине. - Обработать вариант с неавторизованными пользователями (если нужно).
- Проверить поддержку вариаций товаров.
- Добавить кеширование для оптимизации запросов.
- Тестировать на разных ролях пользователей и состояниях заказа.