Как добавить свои поля оформления заказа в WooCommerce…

Как добавить свои поля оформления заказа в WooCommerce…

Как добавить свои поля оформления заказа в 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>';
    }
}
728x90 13

Вывод полей в 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() для ручного вывода.

Мощный SEO плагин Clearfy

Вывод

Кастомные поля оформления заказа — это то, с чем сталкивается каждый WooCommerce-разработчик. Базовая схема проста: фильтр → хуки сохранения и валидации → вывод в админке и письмах. Сложность растёт, когда появляются условная логика, файлы или интеграция с внешними сервисами.

Главный совет: выносите кастомные поля в отдельный MU-плагин или дочернюю тему. Не редактируйте файлы ядра и не кладите код в functions.php основной темы.

Если нужна помощь с кастомизацией WooCommerce или разработкой магазина под ключ — свяжитесь с нами. Поможем с настройкой, интеграциями и уникальным функционалом.

Поделиться:
Telegram ВКонтакте