Диагностика задачи: зачем нужна собственная опция в корзине WooCommerce
Стандартная корзина WooCommerce не предусматривает дополнительных пользовательских опций на этапе просмотра товаров в корзине. Часто требуется добавить, например, выбор подарочной упаковки, способа доставки или дополнительной услуги, чтобы клиент мог сразу внести дополнительные параметры заказа.
В наших проектах часто возникает потребность добавить именно такую опцию, которая влияет на итоговую цену или передается в заказ. Чтобы реализовать это без сторонних плагинов и с полной кастомизацией, потребуется вмешаться в шаблон корзины и использовать хуки WooCommerce.
Пошаговое решение: добавляем собственное поле выбора в корзину
1. Добавление поля выбора в строку товара корзины
Используем хук woocommerce_after_cart_item_name, чтобы вывести HTML с опцией:
add_action('woocommerce_after_cart_item_name', 'add_custom_option_to_cart_item', 20, 2);
function add_custom_option_to_cart_item($cart_item, $cart_item_key) {
$selected = isset($cart_item['custom_option']) ? $cart_item['custom_option'] : '';
echo '<label for="custom_option_'.esc_attr($cart_item_key).'">Подарочная упаковка:</label>';
echo '<select name="custom_option['.esc_attr($cart_item_key).']" id="custom_option_'.esc_attr($cart_item_key).'">';
echo '<option value=""'.selected($selected, '', false).'>Нет</option>';
echo '<option value="yes"'.selected($selected, 'yes', false).'>Да (+100 руб)</option>';
echo '</select>';
}2. Обработка данных при обновлении корзины
Чтобы сохранить выбранное значение, используем хук woocommerce_cart_updated:
add_action('woocommerce_cart_updated', 'save_custom_option_in_cart');
function save_custom_option_in_cart() {
if (empty($_POST['custom_option']) || !is_array($_POST['custom_option'])) {
return;
}
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
if (isset($_POST['custom_option'][$cart_item_key])) {
WC()->cart->cart_contents[$cart_item_key]['custom_option'] = sanitize_text_field($_POST['custom_option'][$cart_item_key]);
}
}
}3. Включение опции в расчет цены товара
Используем фильтр woocommerce_before_calculate_totals, чтобы добавить стоимость упаковки, если выбрана:
add_action('woocommerce_before_calculate_totals', 'add_custom_option_price', 20, 1);
function add_custom_option_price($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if (isset($cart_item['custom_option']) && $cart_item['custom_option'] === 'yes') {
$extra_cost = 100; // рубли
$cart_item['data']->set_price($cart_item['data']->get_price() + $extra_cost);
}
}
}4. Сохранение опции в метаданных заказа
Чтобы опция была видна в админке и в письмах, добавим в заказ:
add_action('woocommerce_add_order_item_meta', 'save_custom_option_to_order_items', 10, 3);
function save_custom_option_to_order_items($item_id, $values, $cart_item_key) {
if (isset($values['custom_option'])) {
wc_add_order_item_meta($item_id, 'Подарочная упаковка', $values['custom_option'] === 'yes' ? 'Да' : 'Нет');
}
}Как проверить, что решение работает
- Перейдите в корзину, выберите опцию «Подарочная упаковка» для товара и нажмите «Обновить корзину».
- Убедитесь, что выбранное значение сохраняется после обновления страницы.
- Проверьте, что стоимость товара увеличилась на 100 рублей, если выбрана упаковка.
- Оформите заказ и в админке WooCommerce в разделе заказа проверьте, что метаданные по упаковке отображаются у позиции товара.
- Проверьте письмо с подтверждением заказа — опция должна отображаться в деталях товара.
Частые ошибки и как их исправить
- Опция не сохраняется после обновления корзины: проверьте, что имя поля
name="custom_option[cart_item_key]"совпадает с обработкой в PHP и что данные передаются в$_POST. - Цена не меняется: убедитесь, что хук
woocommerce_before_calculate_totalsдобавлен с приоритетом выше 20, и вы модифицируете объект$cart_item['data']правильно. - Опция не отображается в заказе: используйте хук
woocommerce_add_order_item_metaдля сохранения метаданных заказа и убедитесь, что используете правильные ключи. - Проблемы с кешированием: если используете плагин кеширования, после внесения изменений очистите кеш, иначе изменения могут не отобразиться.
Практические советы по безопасности и производительности
- Используйте
sanitize_text_fieldдля очистки пользовательских данных из$_POST, чтобы избежать XSS и других уязвимостей. - Добавляйте минимальные изменения в расчет цены, чтобы не нарушить логику WooCommerce и не вызвать конфликт с другими плагинами.
- Тестируйте на staging-среде перед внедрением в рабочий магазин.
- Для больших магазинов с сотнями товаров в корзине можно оптимизировать обработку, объединяя логику и уменьшая количество циклов по корзине.
Сравнение вариантов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
| Код в functions.php | Максимальная гибкость, отсутствие сторонних плагинов | Требует знаний PHP, риск ошибок при обновлениях |
| Плагин для дополнительных опций | Быстрая установка, готовый интерфейс | Может быть лишний функционал, влияние на производительность, зависимость от обновлений плагина |
| Использование кастомных полей товаров | Поддерживается WooCommerce, подходит для простых вариантов | Менее удобно для опций на уровне корзины, не всегда отображается в нужных местах |