Проблема: необходимость уникальной идентификации товаров в WooCommerce
В интернет-магазинах часто требуется присваивать каждому товару уникальный серийный номер (например, для электроники, ПО, гарантийного обслуживания). Стандартный WooCommerce не предоставляет встроенных средств для хранения и проверки уникальных серийных номеров при оформлении заказа. В результате пользователи могут вводить дубли или недопустимые номера, что приводит к ошибкам в учёте и усложняет поддержку.
Как диагностировать проблему с серийными номерами
- Отсутствие поля для ввода серийного номера на странице товара или в корзине.
- Невозможность проверить уникальность введённого номера при оформлении заказа.
- Отсутствие отображения или сохранения серийного номера в заказах WooCommerce.
- Ошибки при попытке ввести повторяющийся номер или формат, не соответствующий требованиям.
Пошаговое решение: добавляем уникальные серийные номера в WooCommerce
1. Добавление поля ввода серийного номера в корзину
Добавим поле для ввода серийного номера для каждого товара в корзине с помощью хука woocommerce_after_cart_item_name:
add_action('woocommerce_after_cart_item_name', 'add_serial_number_field_to_cart', 10, 2);
function add_serial_number_field_to_cart($cart_item, $cart_item_key) {
$serial_number = isset($cart_item['serial_number']) ? $cart_item['serial_number'] : '';
echo '<label for="serial_number_'.esc_attr($cart_item_key).'">Серийный номер:</label>';
echo '<input type="text" name="serial_number['.esc_attr($cart_item_key).']" id="serial_number_'.esc_attr($cart_item_key).'" value="'.esc_attr($serial_number).'" size="20" />';
}2. Сохраняем введённые серийные номера в сессии корзины
Обработаем данные из формы корзины, сохраним серийные номера в элементах корзины:
add_action('woocommerce_cart_updated', 'save_serial_numbers_in_cart');
function save_serial_numbers_in_cart() {
if (isset($_POST['serial_number']) && is_array($_POST['serial_number'])) {
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
if (!empty($_POST['serial_number'][$cart_item_key])) {
WC()->cart->cart_contents[$cart_item_key]['serial_number'] = sanitize_text_field($_POST['serial_number'][$cart_item_key]);
}
}
}
}3. Проверка уникальности при обновлении корзины
Добавим проверку, чтобы серийные номера не дублировались среди товаров в корзине:
add_action('woocommerce_check_cart_items', 'validate_unique_serial_numbers');
function validate_unique_serial_numbers() {
$serials = [];
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
if (!empty($cart_item['serial_number'])) {
$sn = $cart_item['serial_number'];
if (in_array($sn, $serials)) {
wc_add_notice('Серийный номер "'.esc_html($sn).'" повторяется. Пожалуйста, укажите уникальный номер для каждого товара.', 'error');
} else {
$serials[] = $sn;
}
} else {
wc_add_notice('Пожалуйста, укажите серийный номер для всех товаров.', 'error');
}
}
}4. Сохранение серийного номера в метаданные заказа
Чтобы сохранить серийные номера в заказе и отображать их в админке и письмах, используем хуки woocommerce_checkout_create_order_line_item:
add_action('woocommerce_checkout_create_order_line_item', 'add_serial_number_to_order_items', 10, 4);
function add_serial_number_to_order_items($item, $cart_item_key, $values, $order) {
if (!empty($values['serial_number'])) {
$item->add_meta_data('Серийный номер', $values['serial_number']);
}
}Проверка результата после внедрения
- Зайдите в корзину и убедитесь, что для каждого товара отображается поле «Серийный номер».
- Попробуйте ввести одинаковые номера для разных товаров — должно появиться сообщение об ошибке.
- Оформите заказ, проверьте в админке WooCommerce, что в деталях заказа у товаров отображаются введённые серийные номера.
- Проверьте в письмах покупателю, что серийные номера корректно передаются (при необходимости добавьте в шаблоны письмо).
Частые ошибки и как их исправить
- Поле не сохраняется после обновления корзины: проверьте, что обработчик
woocommerce_cart_updatedкорректно обрабатывает и сохраняет данные вcart_contents. - Дубли серийных номеров не выявляются: убедитесь, что проверка
validate_unique_serial_numbersподключена и правильно перебирает все элементы корзины. - Серийный номер не отображается в заказе: проверьте, что метаданные добавляются через
add_meta_dataв хукеwoocommerce_checkout_create_order_line_item. - Проблемы с валидацией формата номера: добавьте дополнительную проверку формата (регулярное выражение) в функцию валидации.
Практические советы по безопасности и производительности
- Всегда используйте функцию
sanitize_text_fieldдля очистки пользовательских данных. - Проверяйте уникальность не только в корзине, но и при сохранении заказа, чтобы исключить дубли с уже существующими серийными номерами (если они хранятся в базе).
- Перегрузка корзины дополнительными полями может замедлить работу — ограничьте длину и формат вводимых номеров.
- Если необходимо массовое управление серийными номерами, рассмотрите хранение их в отдельной таблице базы данных с индексами для быстрой проверки уникальности.
Сравнение способов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
Добавление поля в корзину и сохранение в cart_contents | Простота, не требует внешних плагинов | Не сохраняет серийные номера для повторных заказов, требует кастомного кода |
| Использование плагина для серийных номеров (например, WooCommerce Serial Numbers) | Готовое решение с поддержкой, удобный интерфейс | Платно, ограничена кастомизация, нагрузка плагина |
| Хранение в отдельной таблице с API для проверки | Максимальная производительность и гибкость | Требует глубоких знаний, сложность поддержки |