Клиент прислал макет карточки товара, и вы вдруг поняли: стандартных атрибутов WooCommerce не хватает. Нужно вывести толщину материала, время зарядки, класс энергоэффективности — да что угодно. Первый инстинкт — поставить Advanced Custom Fields, создать группу полей и подключить к продукту. Всё работает, все довольны.

А потом обновляется WordPress, ACF выкатывает мажорный релиз, и на продакшене что-то ломается. Или клиент не хочет платить за ACF PRO, потому что ему нужен всего один тип записи. Или вы разрабатываете плагин, который нельзя привязывать к сторонним зависимостям.

Знакомая ситуация? Тогда давайте разберёмся, как создать кастомные поля для товаров WooCommerce вручную — через нативные инструменты WordPress и хуки самой WooCommerce. Никаких сторонних плагинов, полный контроль над кодом.

Зачем отказываться от ACF при работе с WooCommerce

Не хочу показаться максималистом — ACF отличный инструмент. Мы сами используем его на ряде проектов в WeNesis, когда объём полей большой и нужен удобный UI для редактирования контента. Но есть ситуации, когда нативный подход предпочтительнее:

  • Минимум зависимостей. Каждый плагин — это потенциальная точка отказа. Чем меньше стороннего кода, тем стабильнее сайт.
  • Производительность. ACF подгружает JS- и CSS-файлы на фронте и в админке. Для простых текстовых или числовых полей это избыточно.
  • Разработка плагинов. Если вы создаёте расширение для WooCommerce, вшивать зависимость от ACF — плохая практика.
  • Стоимость. Бесплатная версия ACF хороша, но некоторые типы полей (галерея, повторитель, связанные записи) доступны только в PRO.

WordPress уже имеет мощный API для работы с метаданными. WooCommerce, в свою очередь, предоставляет хуки для встраивания полей прямо в интерфейс редактирования товара. Этого достаточно для большинства задач.

Как устроены метаданные товара WooCommerce

Каждый товар в WooCommerce — это пост с типом product. Все его данные (цена, артикул, вес) хранятся в таблице wp_postmeta как пары «ключ — значение». Никакой магии — стандартный механизм WordPress.

Когда вы задаёте цену товара 1500 рублей, WooCommerce сохраняет в постмету:

  • _price = 1500
  • _regular_price = 1500

Префикс с нижним подчёркиванием означает «скрытое» поле — оно не отображается в обычном списке произвольных полей на странице поста. Мы можем использовать тот же механизм для своих полей.

Добавление полей через хуки WooCommerce

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

Шаг 1: выводим поле в админке

Добавим текстовое поле, например, для указания страны-производителя товара. Код помещаем в functions.php нашей темы (или в файл плагина — если разрабатываем расширение):

add_action( 'woocommerce_product_options_general_product_data', 'wenesis_add_custom_field_manufacturer_country' );

function wenesis_add_custom_field_manufacturer_country() {
    echo '<div class="options_group">';

    woocommerce_wp_text_input( array(
        'id'          => '_manufacturer_country',
        'label'       => 'Страна производства',
        'description' => 'Укажите страну-производителя',
        'desc_tip'    => true,
        'type'        => 'text',
    ) );

    echo '</div>';
}

Функция woocommerce_wp_text_input() — внутренний хелпер WooCommerce, который генерирует разметку, идентичную стандартным полям цены и артикула. Ваше поле будет выглядеть нативно, без дополнительных стилей.

Шаг 2: сохраняем значение

add_action( 'woocommerce_process_product_meta', 'wenesis_save_custom_field_manufacturer_country' );

function wenesis_save_custom_field_manufacturer_country( $post_id ) {
    $value = isset( $_POST['_manufacturer_country'] )
        ? sanitize_text_field( $_POST['_manufacturer_country'] )
        : '';

    update_post_meta( $post_id, '_manufacturer_country', $value );
}

Обратите внимание на sanitize_text_field() — никогда не сохраняйте пользовательский ввод без очистки. Даже если это админка вашего сайта. Привычка санитизировать всё спасёт от XSS и случайных ошибок.

Шаг 3: отображаем поле на фронтенде

Теперь нужно вывести значение на странице товара. Есть несколько мест, куда это можно вписать:

add_action( 'woocommerce_single_product_summary', 'wenesis_display_manufacturer_country', 25 );

function wenesis_display_manufacturer_country() {
    global $product;

    $country = get_post_meta( $product->get_id(), '_manufacturer_country', true );

    if ( ! empty( $country ) ) {
        echo '<div class="product-manufacturer-country">';
        echo '<span class="label">Страна производства:</span> ';
        echo '<span class="value">' . esc_html( $country ) . '</span>';
        echo '</div>';
    }
}

Число 25 в хуке — это приоритет. Для справки: название товара выводится с приоритетом 5, цена — 10, краткое описание — 20, кнопка «В корзину» — 30. Подбирая значение, вы контролируете расположение элемента.

Типы полей, которые можно создать нативно

Хелпер woocommerce_wp_text_input() — не единственный инструмент. WooCommerce предоставляет целый набор функций для генерации разных типов полей в админке.

Выпадающий список (select)

woocommerce_wp_select( array(
    'id'      => '_product_size',
    'label'   => 'Размер',
    'options' => array(
        ''    => 'Выберите размер',
        'S'   => 'Small',
        'M'   => 'Medium',
        'L'   => 'Large',
        'XL'  => 'Extra Large',
    ),
) );

Чекбокс

woocommerce_wp_checkbox( array(
    'id'          => '_is_eco_friendly',
    'label'       => 'Эко-товар',
    'description' => 'Отметьте, если товар произведён из экологичных материалов',
) );

Текстовое поле (textarea)

woocommerce_wp_textarea_input( array(
    'id'          => '_care_instructions',
    'label'       => 'Инструкция по уходу',
    'description' => 'Подробные рекомендации по уходу за товаром',
    'desc_tip'    => true,
    'rows'        => 5,
    'cols'        => 40,
) );

Числовое поле

woocommerce_wp_text_input( array(
    'id'    => '_warranty_months',
    'label' => 'Гарантия (мес.)',
    'type'  => 'number',
    'custom_attributes' => array(
        'min'  => 0,
        'step' => 1,
    ),
) );

Скрытый checkbox с привязкой к WooCommerce-переключателю

woocommerce_wp_hidden_input( array(
    'id'    => '_internal_flag',
    'value' => 'yes',
) );

Как видите, библиотека готовых компонентов достаточно широкая. Для большинства интернет-магазинов этого хватает с запасом.

Добавление полей в собственную вкладку данных товара

Когда стандартные секции («Общие», «Инвентарь», «Доставка») не подходят — можно создать отдельную вкладку в блоке «Данные товара».

add_filter( 'woocommerce_product_data_tabs', 'wenesis_add_product_data_tab' );

function wenesis_add_product_data_tab( $tabs ) {
    $tabs['custom_specs'] = array(
        'label'    => 'Характеристики',
        'target'   => 'custom_specs_product_data',
        'class'    => array(),
        'priority' => 21,
    );

    return $tabs;
}

Теперь нужно наполнить эту вкладку контентом:

add_action( 'woocommerce_product_data_panels', 'wenesis_render_custom_tab_panel' );

function wenesis_render_custom_tab_panel() {
    echo '<div id="custom_specs_product_data" class="panel woocommerce_options_panel">';

    echo '<div class="options_group">';

    woocommerce_wp_text_input( array(
        'id'    => '_spec_voltage',
        'label' => 'Напряжение',
    ) );

    woocommerce_wp_text_input( array(
        'id'    => '_spec_power',
        'label' => 'Мощность',
    ) );

    woocommerce_wp_text_input( array(
        'id'    => '_spec_weight',
        'label' => 'Вес (кг)',
        'type'  => 'number',
    ) );

    echo '</div>';
    echo '</div>';
}

Сохранение — через тот же хук woocommerce_process_product_meta, значения полей просто придут в массиве $_POST.

Работа с пользовательскими полями: получение и вывод значений

После сохранения данные лежат в wp_postmeta. Получить их можно стандартной функцией WordPress:

$country = get_post_meta( $product->get_id(), '_manufacturer_country', true );
[/php>

<p>Третий аргумент <code>true</code> означает, что мы хотим получить одно значение, а не массив. Для большинства полей товаров это именно то, что нужно.</p>

<h3>Вывод в шаблоне карточки товара</h3>

[php]
global $product;

$specs = array(
    '_spec_voltage'         => 'Напряжение',
    '_spec_power'           => 'Мощность',
    '_manufacturer_country' => 'Страна производства',
    '_warranty_months'      => 'Гарантия',
);

echo '<table class="product-specs-table">';

foreach ( $specs as $meta_key => $label ) {
    $value = get_post_meta( $product->get_id(), $meta_key, true );

    if ( ! empty( $value ) ) {
        echo '<tr>';
        echo '<th>' . esc_html( $label ) . '</th>';
        echo '<td>' . esc_html( $value ) . '</td>';
        echo '</tr>';
    }
}

echo '</table>';

Использование в REST API

Если вы строите кастомный фронтенд (headless WordPress, мобильное приложение), метаданные товара удобно получать через REST API. Для этого нужно зарегистрировать метаполе:

add_action( 'rest_api_init', 'wenesis_register_custom_meta_rest' );

function wenesis_register_custom_meta_rest() {
    register_post_meta( 'product', '_manufacturer_country', array(
        'show_in_rest'  => true,
        'single'        => true,
        'type'          => 'string',
    ) );
}

После этого значение поля автоматически появится в ответе эндпоинта /wp-json/wc/v3/products/{id}.

Группа полей: несколько значений в одном поле

Бывает, что для товара нужно хранить не одно значение, а структурированный набор данных. Например, список комплектации. Сериализация — не лучший путь (сложнее искать и фильтровать). Вместо этого используем отдельные метаполя с общим префиксом:

// Вывод полей
add_action( 'woocommerce_product_options_general_product_data', 'wenesis_add_bundle_items' );

function wenesis_add_bundle_items() {
    echo '<div class="options_group">';
    echo '<p class="form-field"><strong>Комплектация</strong></p>';

    for ( $i = 1; $i <= 3; $i++ ) {
        woocommerce_wp_text_input( array(
            'id'    => '_bundle_item_' . $i,
            'label' => 'Позиция ' . $i,
        ) );
    }

    echo '</div>';
}
// Сохранение
add_action( 'woocommerce_process_product_meta', 'wenesis_save_bundle_items' );

function wenesis_save_bundle_items( $post_id ) {
    for ( $i = 1; $i <= 3; $i++ ) {
        $key   = '_bundle_item_' . $i;
        $value = isset( $_POST[ $key ] ) ? sanitize_text_field( $_POST[ $key ] ) : '';
        update_post_meta( $post_id, $key, $value );
    }
}

Кастомные поля для вариативных товаров

Всё, что мы рассматривали выше, работает на уровне всего товара. Но WooCommerce поддерживает вариации — и для каждой можно задать свои метаданные. Это особенно полезно, когда характеристики отличаются в зависимости от размера, цвета или комплектации.

 

Добавить комментарий

Разработка сайтов на Wordpress