Стандартная форма оформления заказа WooCommerce подходит не для каждого магазина. Иногда необходимо запросить дополнительный телефон, удобное время доставки, имя получателя подарка или другую информацию. Сделать это можно с помощью PHP-кода без установки отдельного плагина.

Краткий ответ
Чтобы добавить пользовательское поле в WooCommerce без плагинов, сначала определите тип оформления заказа. Для классической формы используйте фильтр woocommerce_checkout_fields и хуки сохранения заказа. Для блочного оформления Checkout Block используйте Additional Checkout Fields API. После регистрации поля проверьте его валидацию, сохранение, отображение в заказе и совместимость с HPOS.
Какие поля можно добавить в WooCommerce
Чаще всего магазины добавляют дополнительный телефон, идентификационный номер компании, интервал доставки, инструкции курьеру, выбор подарочной упаковки или имя получателя подарка. Не стоит делать необязательную информацию обязательной: длинная форма усложняет покупку.
| Тип | Пример |
|---|---|
| Текст | Имя получателя подарка |
| Телефон | Дополнительный номер |
| Выпадающий список | Время доставки |
| Флажок | Подарочная упаковка |
| Дата | Желаемая дата доставки |
Сначала определите тип оформления заказа
Откройте в WordPress страницу оформления заказа. Если она содержит шорткод [woocommerce_checkout], используется классическая форма. Если на странице установлен блок Checkout, используется блочная форма. Это принципиально: фильтр woocommerce_checkout_fields не добавляет поля в интерфейс Checkout Block.
Примеры ниже предназначены для размещения в functions.php активной дочерней темы. Перед редактированием создайте резервную копию и проверьте изменения на тестовом сайте. В существующий файл functions.php не нужно повторно вставлять открывающий тег PHP.
Добавление полей в классическую форму WooCommerce

Дополнительный телефон покупателя
Следующий код добавляет необязательное поле в группу платёжных данных:
add_filter( 'woocommerce_checkout_fields', 'myshop_add_extra_phone' );
function myshop_add_extra_phone( $fields ) {
$fields['billing']['billing_extra_phone'] = array(
'type' => 'tel',
'label' => 'Дополнительный телефон',
'placeholder' => 'Введите номер телефона',
'required' => false,
'class' => array( 'form-row-wide' ),
'priority' => 115,
);
return $fields;
}
Параметр required определяет обязательность, priority — порядок вывода, а form-row-wide обычно растягивает поле на ширину строки.
Сохранение дополнительного телефона в заказе
Одного вывода поля недостаточно: значение нужно сохранить. Используем объект заказа и его API, совместимый с HPOS.
add_action( 'woocommerce_checkout_create_order', 'myshop_save_extra_phone', 10, 2 );
function myshop_save_extra_phone( $order, $data ) {
if ( isset( $_POST['billing_extra_phone'] ) && is_string( $_POST['billing_extra_phone'] ) ) {
$phone = sanitize_text_field( wp_unslash( $_POST['billing_extra_phone'] ) );
$order->update_meta_data( '_billing_extra_phone', $phone );
}
}
Вывод телефона в карточке заказа
add_action( 'woocommerce_admin_order_data_after_billing_address', 'myshop_show_extra_phone' );
function myshop_show_extra_phone( $order ) {
$phone = $order->get_meta( '_billing_extra_phone' );
if ( $phone !== '' ) {
echo '<p><strong>Дополнительный телефон:</strong> ' . esc_html( $phone ) . '</p>';
}
}
Выпадающий список времени доставки
В классической форме можно добавить список временных интервалов:
add_filter( 'woocommerce_checkout_fields', 'myshop_add_delivery_time' );
function myshop_add_delivery_time( $fields ) {
$fields['billing']['billing_delivery_time'] = array(
'type' => 'select',
'label' => 'Удобное время доставки',
'required' => false,
'class' => array( 'form-row-wide' ),
'priority' => 120,
'options' => array(
'' => 'Выберите время',
'09:00-12:00' => '09:00–12:00',
'12:00-15:00' => '12:00–15:00',
'15:00-18:00' => '15:00–18:00',
),
);
return $fields;
}
add_action( 'woocommerce_checkout_create_order', 'myshop_save_delivery_time', 10, 2 );
function myshop_save_delivery_time( $order, $data ) {
if ( ! isset( $_POST['billing_delivery_time'] ) || ! is_string( $_POST['billing_delivery_time'] ) ) {
return;
}
$value = sanitize_text_field( wp_unslash( $_POST['billing_delivery_time'] ) );
$allowed = array( '09:00-12:00', '12:00-15:00', '15:00-18:00' );
if ( in_array( $value, $allowed, true ) ) {
$order->update_meta_data( '_billing_delivery_time', $value );
}
}
Список разрешённых значений проверяется на сервере: покупатель может изменить данные формы через инструменты разработчика.
Флажок «Подарочная упаковка»
add_filter( 'woocommerce_checkout_fields', 'myshop_add_gift_wrap' );
function myshop_add_gift_wrap( $fields ) {
$fields['order']['myshop_gift_wrap'] = array(
'type' => 'checkbox',
'label' => 'Добавить подарочную упаковку',
'required' => false,
'priority' => 25,
);
return $fields;
}
add_action( 'woocommerce_checkout_create_order', 'myshop_save_gift_wrap', 10, 2 );
function myshop_save_gift_wrap( $order, $data ) {
$enabled = isset( $_POST['myshop_gift_wrap'] ) && '1' === sanitize_text_field( wp_unslash( $_POST['myshop_gift_wrap'] ) );
$order->update_meta_data( '_myshop_gift_wrap', $enabled ? 'yes' : 'no' );
}
Этот код только сохраняет выбор. Если упаковка платная, потребуется отдельно добавить стоимость к заказу.
Поле после примечаний к заказу
Для вывода поля в отдельной позиции можно использовать woocommerce_after_order_notes.
add_action( 'woocommerce_after_order_notes', 'myshop_add_customer_source' );
function myshop_add_customer_source( $checkout ) {
woocommerce_form_field( 'myshop_customer_source', array(
'type' => 'text',
'label' => 'Как вы узнали о магазине?',
'placeholder' => 'Например, Google',
'required' => false,
'class' => array( 'form-row-wide' ),
), $checkout->get_value( 'myshop_customer_source' ) );
}
add_action( 'woocommerce_checkout_create_order', 'myshop_save_customer_source', 10, 2 );
function myshop_save_customer_source( $order, $data ) {
if ( isset( $_POST['myshop_customer_source'] ) && is_string( $_POST['myshop_customer_source'] ) ) {
$value = sanitize_text_field( wp_unslash( $_POST['myshop_customer_source'] ) );
$order->update_meta_data( '_myshop_customer_source', $value );
}
}
Как изменить стандартные поля оформления заказа
Сделать компанию необязательной
add_filter( 'woocommerce_checkout_fields', 'myshop_optional_company' );
function myshop_optional_company( $fields ) {
if ( isset( $fields['billing']['billing_company'] ) ) {
$fields['billing']['billing_company']['required'] = false;
}
return $fields;
}
Переименовать комментарий к заказу
add_filter( 'woocommerce_checkout_fields', 'myshop_rename_order_comments' );
function myshop_rename_order_comments( $fields ) {
if ( isset( $fields['order']['order_comments'] ) ) {
$fields['order']['order_comments']['label'] = 'Комментарий для менеджера';
}
return $fields;
}
Изменить порядок полей
add_filter( 'woocommerce_checkout_fields', 'myshop_reorder_checkout' );
function myshop_reorder_checkout( $fields ) {
if ( isset( $fields['billing']['billing_phone'] ) ) {
$fields['billing']['billing_phone']['priority'] = 15;
}
if ( isset( $fields['billing']['billing_email'] ) ) {
$fields['billing']['billing_email']['priority'] = 20;
}
return $fields;
}
Удалить ненужное поле
add_filter( 'woocommerce_checkout_fields', 'myshop_remove_company' );
function myshop_remove_company( $fields ) {
unset( $fields['billing']['billing_company'] );
return $fields;
}
Важно: не удаляйте без проверки страну, индекс или адрес доставки. Эти данные могут участвовать в расчёте налогов, тарифов доставки и проверках платёжных систем.
Добавление полей в WooCommerce Checkout Block

Блочное оформление заказа использует отдельный механизм — woocommerce_register_additional_checkout_field(). Он позволяет регистрировать поля в областях contact, address и order. В отличие от классической формы, сохранение зарегистрированных полей обрабатывается самим API.
Текстовое поле «Имя получателя подарка»
add_action( 'woocommerce_init', 'myshop_register_gift_recipient' );
function myshop_register_gift_recipient() {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
woocommerce_register_additional_checkout_field( array(
'id' => 'myshop/gift-recipient',
'label' => 'Имя получателя подарка',
'location' => 'order',
'type' => 'text',
'required' => false,
) );
}
Идентификатор поля должен включать собственное пространство имён и уникальное название, например myshop/gift-recipient.
Выпадающий список в Checkout Block
add_action( 'woocommerce_init', 'myshop_register_customer_source' );
function myshop_register_customer_source() {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
woocommerce_register_additional_checkout_field( array(
'id' => 'myshop/customer-source',
'label' => 'Откуда вы узнали о нас?',
'location' => 'order',
'type' => 'select',
'required' => false,
'options' => array(
array( 'value' => 'google', 'label' => 'Поиск Google' ),
array( 'value' => 'social', 'label' => 'Социальные сети' ),
array( 'value' => 'friends', 'label' => 'Рекомендация знакомых' ),
array( 'value' => 'other', 'label' => 'Другой источник' ),
),
) );
}
Флажок «Это подарок»
add_action( 'woocommerce_init', 'myshop_register_is_gift' );
function myshop_register_is_gift() {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
woocommerce_register_additional_checkout_field( array(
'id' => 'myshop/is-gift',
'label' => 'Это подарок',
'location' => 'order',
'type' => 'checkbox',
'required' => false,
) );
}
Читайте также:
Выбор желаемой даты доставки
add_action( 'woocommerce_init', 'myshop_register_delivery_date' );
function myshop_register_delivery_date() {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
woocommerce_register_additional_checkout_field( array(
'id' => 'myshop/delivery-date',
'label' => 'Желаемая дата доставки',
'location' => 'order',
'type' => 'date',
'required' => false,
) );
}
Выбор даты сам по себе не гарантирует доступность доставки. Для ограничения выходных, праздников и занятых интервалов потребуется дополнительная логика проверки.
Получение значения дополнительного поля Checkout Block
Для чтения данных используйте сервис CheckoutFields. Следующий фрагмент предполагает, что переменная $order уже содержит объект WC_Order.
$checkout_fields = \Automattic\WooCommerce\Blocks\Package::container()->get(
\Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields::class
);
$value = $checkout_fields->get_field_from_object(
'myshop/gift-recipient',
$order,
'other'
);
Для полей области order используется группа other. Для адресных полей применяются соответствующие группы billing и shipping. Не следует самостоятельно предполагать формат внутренних ключей метаданных блочных полей.
Валидация пользовательских полей
Новые поля нужно проверять на сервере, особенно если они используются при доставке, выставлении документов или передаче данных во внешние системы.
Проверка дополнительного телефона в классической форме
add_action( 'woocommerce_after_checkout_validation', 'myshop_validate_extra_phone', 10, 2 );
function myshop_validate_extra_phone( $data, $errors ) {
if ( empty( $data['billing_extra_phone'] ) ) {
return;
}
$phone = trim( $data['billing_extra_phone'] );
if ( ! preg_match( '/^\+?[0-9\s\-\(\)]{7,25}$/', $phone ) ) {
$errors->add( 'invalid_extra_phone', 'Проверьте дополнительный номер телефона.' );
}
}
Это базовая проверка допустимых символов и длины, а не подтверждение существования номера. Для Checkout Block применяются отдельные хуки проверки Additional Checkout Fields API и поддерживаемые ограничения атрибутов.
Совместимость с HPOS
High-Performance Order Storage (HPOS) использует специализированное хранилище заказов. Для пользовательских метаданных безопаснее применять методы объекта заказа, а не напрямую вызывать update_post_meta().
$order = wc_get_order( $order_id );
if ( $order ) {
$order->update_meta_data( '_myshop_custom_field', $value );
$order->save();
}
Если значение сохраняется внутри хука woocommerce_checkout_create_order, дополнительный вызов save() обычно не нужен: WooCommerce сохранит заказ в рамках оформления покупки.
Как показать дополнительное поле в письме WooCommerce
Например, выбранный интервал доставки можно вывести в уведомлениях о заказе.
add_action( 'woocommerce_email_after_order_table', 'myshop_email_delivery_time', 10, 4 );
function myshop_email_delivery_time( $order, $sent_to_admin, $plain_text, $email ) {
$time = $order->get_meta( '_billing_delivery_time' );
if ( empty( $time ) ) {
return;
}
if ( $plain_text ) {
echo "\nВремя доставки: " . esc_html( $time ) . "\n";
} else {
echo '<p><strong>Время доставки:</strong> ' . esc_html( $time ) . '</p>';
}
}
Для полей Checkout Block используйте соответствующий API чтения значений, а не метаключи из примеров для классической формы.
Частые ошибки и способы исправления
| Проблема | Что проверить |
|---|---|
| Поле не видно | Тип формы: Classic Checkout или Checkout Block |
| Значение не сохраняется | Хук сохранения и имя поля |
| Ошибка PHP | Синтаксис, уникальность названий функций |
| Поле дублируется | Повторное подключение фрагмента |
| Нет данных в админке | Правильный метаключ или API чтения |
| Проблемы с HPOS | Использование CRUD API WooCommerce |
Контрольный список перед публикацией
- Проверить форму на компьютере и смартфоне.
- Оформить тестовый заказ как гость и как зарегистрированный покупатель.
- Проверить обязательность и ошибки валидации.
- Убедиться, что данные сохранились в заказе.
- Проверить отображение в админке и письмах.
- Проверить разные способы доставки и оплаты.
- Проверить работу при включённом HPOS.
PHP-код или плагин: что выбрать?
Для одного-двух простых полей собственные PHP-фрагменты позволяют избежать дополнительного расширения и гибко контролировать поведение формы. Но если нужны десятки полей, условные зависимости, сложные интерфейсы и интеграции с CRM, специализированный плагин может оказаться удобнее в обслуживании.
Отсутствие плагина не означает отсутствия поддержки: после обновлений WooCommerce пользовательский код необходимо повторно тестировать.
FAQ: часто задаваемые вопросы
Добавить пользовательские поля в WooCommerce без плагинов вполне реально. Для классического оформления заказа подходят woocommerce_checkout_fields и хуки сохранения заказа; для Checkout Block — Additional Checkout Fields API. Важно не только вывести новое поле, но и обеспечить проверку данных, безопасное сохранение, совместимость с HPOS и удобство покупателей. Начинайте с минимального набора действительно нужных полей и обязательно проверяйте результат на тестовом заказе.
Источники
- WooCommerce Developer Documentation — Customising Checkout Fields.
- WooCommerce — Additional Checkout Fields.
- WooCommerce — Additional Checkout Fields Guide.
- WooCommerce — High-Performance Order Storage.
- WordPress Developer Resources — Hooks.
- WordPress Developer Resources — Data Validation.





















Комментарии к записи: 0