Как добавить свои поля оформления заказа в WooCommerce: полный гайд с кодом
Стандартная форма оформления заказа в WooCommerce покрывает базовые потребности, но в реальных проектах почти всегда требуется добавить свои поля: ИНН для юридических лиц, дату доставки, комментарий курьеру, промокод партнёра или кастомный выбор способа получения. Разберём, как сделать это правильно — через хуки, без редактирования шаблонов ядра.
Быстрый ответ: Добавить поля в чекаут WooCommerce можно через хуки woocommerce_checkout_fields (для создания полей) и woocommerce_checkout_update_order_meta (для сохранения). Выводить поля удобно через woocommerce_form_field(). Для отображения в админке и письмах используйте фильтры woocommerce_order_item_name и woocommerce_email_order_meta. Весь код — в functions.php вашей темы или в кастомном плагине.
Основной фильтр: woocommerce_checkout_fields
Главный инструмент — фильтр woocommerce_checkout_fields. Он принимает массив всех полей формы оформления и возвращает его после ваших изменений. Поля группируются по секциям: billing, shipping, order и account.
Базовая структура
add_filter('woocommerce_checkout_fields', 'add_custom_checkout_fields');
function add_custom_checkout_fields($fields) {
$fields['order']['custom_field'] = array(
'type' => 'text',
'label' => 'Название поля',
'placeholder' => 'Введите значение',
'required' => true,
'class' => array('form-row-wide'),
'priority' => 100,
);
return $fields;
}Параметр type может быть: text, textarea, select, radio, checkbox, date, number, tel и другие. priority управляет порядком вывода внутри секции.
Добавляем ИНН для юрлиц (select с условным показом)
Частая задача — показать поле ИНН, если выбран тип плательщика «Юридическое лицо». Реализуем через select + JavaScript.
Шаг 1: Добавляем поля в functions.php
add_filter('woocommerce_checkout_fields', 'add_inn_field_for_companies');
function add_inn_field_for_companies($fields) {
// Поле выбора типа плательщика
$fields['billing']['billing_payer_type'] = array(
'type' => 'select',
'label' => 'Тип плательщика',
'required' => true,
'options' => array(
'individual' => 'Физическое лицо',
'legal' => 'Юридическое лицо',
),
'class' => array('form-row-wide'),
'priority' => 25,
);
// Поле ИНН (будет скрыто по умолчанию)
$fields['billing']['billing_inn'] = array(
'type' => 'text',
'label' => 'ИНН организации',
'required' => false,
'class' => array('form-row-wide', 'inn-field'),
'priority' => 26,
);
return $fields;
}Шаг 2: JavaScript для условного показа
add_action('wp_footer', 'checkout_toggle_inn_field');
function checkout_toggle_inn_field() {
if (!is_checkout()) return;
?>
<script type="text/javascript">
jQuery(function($) {
function toggleInnField() {
var val = $('#billing_payer_type').val();
if (val === 'legal') {
$('.inn-field').show();
$('#billing_inn').prop('required', true);
} else {
$('.inn-field').hide();
$('#billing_inn').prop('required', false).val('');
}
}
$(document).on('change', '#billing_payer_type', toggleInnField);
toggleInnField();
});
</script>
Сохранение полей в заказ
Добавленные поля не сохранятся автоматически. Нужно подписаться на хук woocommerce_checkout_update_order_meta и сохранить их в мета-поля заказа.
add_action('woocommerce_checkout_update_order_meta', 'save_custom_checkout_fields');
function save_custom_checkout_fields($order_id) {
if (!empty($_POST['billing_payer_type'])) {
update_post_meta($order_id, 'billing_payer_type', sanitize_text_field($_POST['billing_payer_type']));
}
if (!empty($_POST['billing_inn'])) {
update_post_meta($order_id, 'billing_inn', sanitize_text_field($_POST['billing_inn']));
}
}Всегда санитируйте данные (sanitize_text_field, wp_kses_post и т.д.) — это базовая защита от XSS-атак.
Валидация полей перед отправкой
Если поле обязательно только при определённых условиях, валидацию нужно делать вручную через хук woocommerce_checkout_process.
add_action('woocommerce_checkout_process', 'validate_custom_checkout_fields');
function validate_custom_checkout_fields() {
if ($_POST['billing_payer_type'] === 'legal' && empty($_POST['billing_inn'])) {
wc_add_notice('Пожалуйста, укажите ИНН организации', 'error');
}
// Проверка формата ИНН (10 цифр для юрлиц)
if (!empty($_POST['billing_inn']) && !preg_match('/^d{10}$/', $_POST['billing_inn'])) {
wc_add_notice('ИНН должен содержать 10 цифр', 'error');
}
}Отображение полей в админке заказа
Сохранённые мета-поля не отображаются в админке автоматически. Их нужно вывести через хук woocommerce_admin_order_data_after_billing_address.
add_action('woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin');
function display_custom_fields_in_admin($order) {
$payer_type = get_post_meta($order->get_id(), 'billing_payer_type', true);
$inn = get_post_meta($order->get_id(), 'billing_inn', true);
if ($payer_type) {
$label = ($payer_type === 'legal') ? 'Юридическое лицо' : 'Физическое лицо';
echo '<p><strong>Тип плательщика:</strong> ' . esc_html($label) . '</p>';
}
if ($inn) {
echo '<p><strong>ИНН:</strong> ' . esc_html($inn) . '</p>';
}
}
Вывод полей в email-уведомлениях
Чтобы клиент и менеджер видели поля в письмах, используем фильтр woocommerce_email_order_meta.
add_action('woocommerce_email_order_meta', 'display_custom_fields_in_emails', 10, 3);
function display_custom_fields_in_emails($order, $sent_to_admin, $plain_text) {
$inn = get_post_meta($order->get_id(), 'billing_inn', true);
if ($inn) {
if ($plain_text) {
echo "ИНН: " . $inn . "
";
} else {
echo '<p><strong>ИНН:</strong> ' . esc_html($inn) . '</p>';
}
}
}Продвинутый пример: дата доставки + временной слот
Для интернет-магазинов с самовывозом часто нужен выбор даты и времени. Реализуем через datepicker jQuery.
add_filter('woocommerce_checkout_fields', 'add_delivery_datetime_fields');
function add_delivery_datetime_fields($fields) {
$fields['order']['delivery_date'] = array(
'type' => 'text',
'label' => 'Дата доставки',
'placeholder' => 'Выберите дату',
'required' => true,
'class' => array('form-row-first', 'delivery-date-field'),
'priority' => 50,
);
$fields['order']['delivery_time'] = array(
'type' => 'select',
'label' => 'Время доставки',
'required' => true,
'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',
'18:00-21:00' => '18:00 — 21:00',
),
'class' => array('form-row-last'),
'priority' => 51,
);
return $fields;
}Подключаем datepicker
add_action('wp_enqueue_scripts', 'enqueue_checkout_datepicker');
function enqueue_checkout_datepicker() {
if (is_checkout()) {
wp_enqueue_script('jquery-ui-datepicker');
wp_enqueue_style('jquery-ui', 'https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css');
}
}
add_action('wp_footer', 'init_checkout_datepicker');
function init_checkout_datepicker() {
if (!is_checkout()) return;
?>
<script>
jQuery(function($) {
$('#delivery_date').datepicker({
dateFormat: 'dd.mm.yy',
minDate: 0,
maxDate: '+30',
firstDay: 1,
});
});
</script>
Сравнение: добавляем поля в functions.php vs кастомный плагин
| Способ | Плюсы | Минусы |
|---|---|---|
| functions.php темы | Быстро, не требует создания файлов | Теряется при смене темы, раздувает файл |
| MU-плагин | Не зависит от темы, всегда активен | Нужно создавать файл wp-content/mu-plugins/ |
| Кастомный плагин | Можно сложить много логики, легко переносить | Больше кода, нужно подключать через wp-admin |
| Code Snippets | Удобно, не требует доступа к файлам | Зависимость от плагина |
Лично я рекомендую MU-плагин (wp-content/mu-plugins/checkout-custom-fields.php) — он не зависит от темы, всегда включён и не теряется при обновлениях. При разработке сайтов на заказ мы всегда выносим кастомный функционал чекаута в отдельный плагин — так проще поддерживать код.
Типичные ошибки и как их избежать
- Поля не сохраняются — забыли подписаться на
woocommerce_checkout_update_order_meta. - Поле не отображается после обновления WooCommerce — используйте
woocommerce_form_field()вместо прямого HTML. - Кэширование чекаута — фрагментное кэширование может сломать условный показ полей.
- Конфликт с плагинами доставки — некоторые плагины переопределяют
woocommerce_checkout_fields. Проверяйте приоритет фильтра (ставьте 100+, чтобы сработать после всех). - XSS через кастомные поля — всегда экранируйте вывод через
esc_html().
Часто задаваемые вопросы
Как сделать поле обязательным только при определённом условии
Используйте JavaScript (jQuery) для показа/скрытия поля на клиенте, и PHP-валидацию в woocommerce_checkout_process на сервере, чтобы проверить условие и выдать ошибку через wc_add_notice().
Можно ли добавить поле загрузки файла в форму оформления заказа
Да, через тип file и хук woocommerce_checkout_process. Но это сложнее — нужно обработать загрузку через wp_handle_upload() и прикрепить файл к заказу или загрузить в медиатеку. Для продакшена лучше использовать специализированный плагин загрузки файлов.
Как вывести кастомные поля в REST API WooCommerce
Добавьте мета-поле в ответ API через фильтр woocommerce_rest_order_object_query или зарегистрируйте его через register_rest_field. WooCommerce REST API автоматически возвращает meta_data, если поле сохранено.
Что делать, если поля исчезли после обновления темы
Перенесите код в MU-плагин или дочернюю тему. Код в functions.php основной темы сбрасывается при обновлении темы. Подробнее о правильной структуре WordPress-проекта читайте на нашем сайте.
Можно ли группировать кастомные поля в секции
Да. Укажите ключ секции в массиве полей: billing, shipping или order. Для кастомных секций создайте новую группу через хук woocommerce_checkout_before_customer_details или используйте woocommerce_form_field() для ручного вывода.
Вывод
Кастомные поля оформления заказа — это то, с чем сталкивается каждый WooCommerce-разработчик. Базовая схема проста: фильтр → хуки сохранения и валидации → вывод в админке и письмах. Сложность растёт, когда появляются условная логика, файлы или интеграция с внешними сервисами.
Главный совет: выносите кастомные поля в отдельный MU-плагин или дочернюю тему. Не редактируйте файлы ядра и не кладите код в functions.php основной темы.
Если нужна помощь с кастомизацией WooCommerce или разработкой магазина под ключ — свяжитесь с нами. Поможем с настройкой, интеграциями и уникальным функционалом.

