Диагностика проблемы: зачем менять цену и наличие товара динамически
В стандартном WooCommerce все изменения цены или наличия товара требуют перезагрузки страницы или перехода в админку для обновления. Это неудобно для пользователей и замедляет процесс оформления заказа. Например, если цена зависит от выбранных опций или пользовательских условий, нужно менять цену и статус наличия на лету, чтобы не потерять клиента.
Типичные задачи:
- Изменение цены товара при выборе дополнительных опций;
- Динамическое обновление статуса наличия при изменении количества;
- Удаление товара из корзины и обновление цены без перезагрузки.
Как проверить, что стандартное поведение не подходит
Создайте товар с вариациями и попробуйте изменить опцию. Если цена меняется только после обновления страницы, или при удалении товара из корзины страница перезагружается, значит, нужно реализовать AJAX-логику.
Пошаговое решение: AJAX-изменение цены и наличия товара в WooCommerce
1. Добавляем обработчик AJAX в functions.php
Создаем PHP-функцию, которая будет принимать запрос, обрабатывать логику изменения цены и наличия, и возвращать JSON-ответ.
add_action('wp_ajax_update_product_info', 'update_product_info_callback');
add_action('wp_ajax_nopriv_update_product_info', 'update_product_info_callback');
function update_product_info_callback() {
if ( ! isset($_POST['product_id']) ) {
wp_send_json_error('Product ID missing');
}
$product_id = intval($_POST['product_id']);
$product = wc_get_product($product_id);
if (!$product) {
wp_send_json_error('Product not found');
}
// Пример: изменяем цену в зависимости от переданного параметра
$option = isset($_POST['option']) ? sanitize_text_field($_POST['option']) : '';
$price = $product->get_price();
$stock_status = $product->is_in_stock() ? 'instock' : 'outofstock';
// Логика изменения цены и наличия
if ($option === 'special') {
$price = $price * 0.9; // скидка 10%
$stock_status = 'instock';
} elseif ($option === 'limited') {
$stock_status = 'outofstock';
}
wp_send_json_success([
'price' => wc_price($price),
'stock_status' => $stock_status
]);
}2. Добавляем JavaScript для отправки AJAX-запроса и обновления интерфейса
Подключаем скрипт и отправляем AJAX при смене опции. В ответе обновляем цену и статус наличия в DOM.
jQuery(document).ready(function($) {
$('#product-option-select').on('change', function() {
var option = $(this).val();
var productId = $(this).data('product-id');
$.ajax({
url: wc_add_to_cart_params.ajax_url,
type: 'POST',
data: {
action: 'update_product_info',
product_id: productId,
option: option
},
success: function(response) {
if (response.success) {
$('#product-price').html(response.data.price);
if(response.data.stock_status === 'instock') {
$('#stock-status').text('В наличии').removeClass('outofstock').addClass('instock');
} else {
$('#stock-status').text('Нет в наличии').removeClass('instock').addClass('outofstock');
}
} else {
console.error(response.data);
}
},
error: function() {
console.error('AJAX error');
}
});
});
});3. HTML-разметка примера
<select id="product-option-select" data-product-id="123">
<option value="default">Обычная</option>
<option value="special">Специальная</option>
<option value="limited">Ограниченная</option>
</select>
<div id="product-price">₽1000</div>
<div id="stock-status" class="instock">В наличии</div>Проверка результата после внедрения
- При смене опции цена и статус наличия на странице меняются без перезагрузки;
- В консоли браузера нет ошибок AJAX;
- Если передать неверный product_id, возвращается ошибка;
- При отключенном JavaScript изменения не происходят (нужно предусмотреть fallback).
Частые ошибки и как их исправить
- Не подключен wp_localize_script для передачи ajax_url. Решение: добавить в enqueue скрипта
wp_localize_script('script-handle', 'wc_add_to_cart_params', ['ajax_url' => admin_url('admin-ajax.php')]);. - Неверный product_id или пропущенный параметр в AJAX. Проверяйте наличие и типы параметров, используйте
intvalиsanitize_text_field. - Кэширование мешает обновлению цены. Очистите кэш браузера и серверный кэш, отключите плагин кэширования при тестах.
- Отсутствие проверки nonce для безопасности. Рекомендуется добавить nonce и проверять его в обработчике AJAX.
Практические советы по безопасности и производительности
- Добавьте проверку nonce в AJAX-запросах для защиты от CSRF:
// В PHP (functions.php)
add_action('wp_enqueue_scripts', function() {
wp_localize_script('custom-script', 'custom_ajax_obj', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('update_product_nonce')
]);
});
// В обработчике
if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'update_product_nonce')) {
wp_send_json_error('Invalid nonce');
}- Используйте минимально необходимые данные в ответах AJAX, чтобы уменьшить нагрузку.
- Кэшируйте результаты, если логика сложная, чтобы снизить нагрузку на сервер.
- Тестируйте совместимость с основными плагинами кэширования и оптимизации.
Сравнение вариантов реализации: плагин vs кастомный код
| Критерий | Использование плагина | Кастомный код (как в статье) |
|---|---|---|
| Гибкость | Ограничена функционалом плагина | Полная, под любые условия |
| Скорость | Чаще тяжелее, из-за общего кода | Оптимизированный код под задачу |
| Безопасность | Зависит от плагина | Можно встроить nonce и проверки |
| Обновления | Плагин обновляется отдельно | Требует поддержки разработчиком |
| Требования к навыкам | Минимум | Требует знаний PHP и JS |