Клиент прислал макет карточки товара, и вы вдруг поняли: стандартных атрибутов 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 поддерживает вариации — и для каждой можно задать свои метаданные. Это особенно полезно, когда характеристики отличаются в зависимости от размера, цвета или комплектации.
Добавить комментарий