В Woocommerce есть очень мощный API произвольных полей, который позволяет добавлять много разных вкусных решений. В этой статье разберем, как добавлять произвольные поля к простым товарам.
- Теория. Необходимые хуки и функции
- Хуки на вкладках
- Вкладка «Основные»
- Вкладка «Доставка»
- Вкладка «Запасы»
- Вкладка «Сопутствующие»
- Вкладка «Атрибуты»
- Вкладка «Дополнительно»
- Вкладка «Вариации»
- Хуки для сохранения значения полей
- Хуки для вывода полей
- Функции вывода полей
- Практика. Создаем, сохраняем и выводим произвольные поля
- Создание полей
- Текстовое поле
- Числовое поле
- Текстовая область
- Выпадающий список. Select
- Поле с чекбоксом. Checkbox
- Радиокнопки. Radio buttons
- Произвольное поле. Выбор товаров с поиском
- Произвольная группа полей
- Полный код со всеми видами полей, в том числе и произвольными
- Сохранение полей
- Вывод полей
- Перед кнопкой Добавить в корзину
- После кнопки Добавить в корзину
- Вывод группы полей во вкладке Дополнительная информация
- Вывод выбранных товаров перед вкладками с информацией
- Вывод значения полей на страницах архивов
- Группировка произвольных полей на произвольной вкладке
- Создание произвольной вкладки
- Изменение иконки вкладки
- Добавление содержимого вкладки
- Кейс. Дополнительные поля на вкладке «Основные»
- Задача
- Решение
- Первое. Создаем поля
- Второе. Вывод полей
- Третье. Результат
- Кейс. Произвольное текстовое поле с редактором TinyMCE
- Задача
- Решение
- Первое. Создаем новое поле
- Второе. Выводим значение
- Третье. Результат
- Заключение
functions.php
или например пустой плагин. Прежде чем, вносить какие либо изменения, сделайте бекап сайта.Продолжим. Вот такая штука у нас получиться.
к содержаниюТеория. Необходимые хуки и функции
В Woocomerce на любой чих найдется нужный акшион или фильтр (то, что называется хуки). В случае добавления произвольных полей будут использоваться хуки для вывода полей на вкладках метабокса. В зависимости от вкладки можно использовать тот или иной хук. Но следует помнить, что некоторые поля и вкладки могут быть не видны в зависимости от типа товара.
Хуки на вкладках
Вкладка «Основные»
На вкладке «Основные» можно использовать несколько хуков.
woocommerce_product_options_pricing // после цен
woocommerce_product_options_downloads // после скачиваемого файла (для скачиваемых товаров)
woocommerce_product_options_tax // после налоговых ставок
woocommerce_product_options_general_product_data // после основного контента вкладки
Вкладка «Доставка»
Данная вкладка активна только для физических товаров. Все хуки на вкладке «Доставка».
woocommerce_product_options_dimensions // после размеров
woocommerce_product_options_shipping // после основного контента вкладки
Вкладка «Запасы»
Все хуки на вкладке «Запасы».
woocommerce_product_options_sku // после артикула
woocommerce_product_options_stock // перед управлением запасами
woocommerce_product_options_stock_fields // после управлением запасами
woocommerce_product_options_stock_status // после статуса остатка
woocommerce_product_options_sold_individually // после опции Продавать индивидуально
woocommerce_product_options_inventory_product_data // после основного контента вкладки
Вкладка «Сопутствующие»
Все хуки на вкладке «Сопутствующие».
woocommerce_product_options_related // после основного контента вкладки
Вкладка «Атрибуты»
Все хуки на вкладке «Атрибуты».
woocommerce_product_options_attributes // после основного контента вкладки
Вкладка «Дополнительно»
Все хуки на вкладке «Дополнительно».
woocommerce_product_options_reviews // после опции Включить отзывы
woocommerce_product_options_advanced // после основного контента вкладки
Вкладка «Вариации»
Вкладка видна только для вариативных товаров. Все хуки на вкладке «Вариации».
woocommerce_variable_product_before_variations // перед списком вариаций
Хуки для сохранения значения полей
Для сохранения наших полей будем использовать хук.
woocommerce_process_product_meta
Это базовый хук, который позволяет сохранять значения произвольных полей для простых товаров. Хук передает ID товара.
Как создавать произвольные поля для вариативных товаров смотрите в отдельной статье.
к содержаниюХуки для вывода полей
Поля — дело индивидуальное для каждого товара. Товар в Woocomerce — это запись, соответственно можно выводить товары и просто редактируя нужный файл. Но это не наш метод. А потому будем использовать хуки. Например, используем хук для вывода поля перед и после кнопки «Добавить в корзину».
Перед кнопкой
woocommerce_before_add_to_cart_form
После кнопки
woocommerce_after_add_to_cart_form
к содержанию
Функции вывода полей
Согласно API Woocommerce существуют такие функции добавления полей
- Простое поле —
woocommerce_wp_text_input()
; - Область текста —
woocommerce_wp_textarea_input()
; - Скрытое поле —
woocommerce_wp_hidden_input()
; - Поле чекбокса —
woocommerce_wp_checkbox()
; - Выпадающий список —
woocommerce_wp_select()
; - Радиокнопки —
woocommerce_wp_radio()
;
Более подробно посмотреть функции можно в документации
Вот эти функции и будем использовать. Но это еще не все, для большего эффекта, напишем собственные поля, независимые от API.
к содержаниюПрактика. Создаем, сохраняем и выводим произвольные поля
Создание полей
Итак, начнем. Создаем функцию и прикручиваем ее к нужному хуку.
add_action( 'woocommerce_product_options_general_product_data', 'art_woo_add_custom_fields' );
function art_woo_add_custom_fields() {
global $product, $post;
echo '<div class="options_group">';// Группировка полей
//...здесь добавляем нужные функции
echo '</div>';
}
Пока ничего сложного. Просто функция, которая ничего не делает. Блок с классом options_group
позволяет визуально разделять группы полей с помощью нижней границы.
Текстовое поле
// текстовое поле
woocommerce_wp_text_input( array(
'id' => '_text_field',
'label' => __( 'Текстовое поле', 'woocommerce' ),
'placeholder' => 'Текстовое поле',
'desc_tip' => 'true',
'custom_attributes' => array( 'required' => 'required' ),
'description' => __( 'Введите здесь значение поля', 'woocommerce' ),
) );
Обратите внимание, на два момента.
Во-первых, атрибут custom_attributes
позволяет передать в функцию любые дополнительные параметры. В данном конкретно случае — это параметр определяет обязательное поле.
Во-вторых, использование атрибута desc_tip
, позволяет выводить описание поля не как обычно, а во всплывающей подсказке. Иногда это очень удобно. Данный атрибут работает с любым типом полей.
Числовое поле
Это то же простое текстовое поле, но с типом number. Тип из арсенала HTML5 позволяет ограничить ввод данных только числами.
// цифровое поле
woocommerce_wp_text_input( array(
'id' => '_number_field',
'label' => __( 'Цифровое поле', 'woocommerce' ),
'placeholder' => 'Ввод чисел',
'description' => __( 'Вводятся только числа', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '0',
),
) );
Можно определить произвольные атрибуты:
- шаг,
- минимальное и максимальное значение.
Атрибут step
— это значение по умолчанию, min
— минимальное значение. Ожидается ввод любого положительного числа
Текстовая область
// Тектовая область
woocommerce_wp_textarea_input( array(
'id' => '_textarea', // Идентификатор поля
'label' => 'Область текста', // Заголовок поля
'placeholder' => 'Ввод текста', // Надпись внутри поля
'class' => 'textarea-field', // Произвольный класс поля
'style' => 'width: 70%; background:red', // Произвольные стили для поля
'wrapper_class' => 'wrap-textarea', // Класс обертки поля
'desc_tip' => 'true', // Включение подсказки
'description' => 'Здесь можно что-нибудть вводить',// Описение поля
'name' => 'textarea-field', // Имя поля
'rows' => '5', //Высота поля в строках текста.
'col' => '10', //Ширина поля в символах.
) );
Ничего сложно. В конкретном случае еще переданы дополнительные параметры (общие для все типов полей):
class
— позволяет добавлять к полям произвольные класс;style
— добавление произвольных стилей (в данном случае задана ширина и цвет фона);wrapper_class
— произвольный класс для обертки всего поля;name
— собственный параметрname
.
Выпадающий список. Select
// Выбор значения
woocommerce_wp_select( array(
'id' => '_select',
'label' => 'Выпадающий список',
'options' => array(
'one' => __( 'Option 1', 'woocommerce' ),
'two' => __( 'Option 2', 'woocommerce' ),
'three' => __( 'Option 3', 'woocommerce' ),
),
) );
Добавляется параметр options
, в который передается массив значений.
Поле с чекбоксом. Checkbox
// Чекбокс
woocommerce_wp_checkbox( array(
'id' => '_checkbox',
'wrapper_class' => 'show_if_simple',
'label' => 'Чекбокс',
'description' => 'Выбери меня!',
) );
Просто поле с галочкой. Возвращает Да/Нет.
Радиокнопки. Radio buttons
// Радиокнопки
woocommerce_wp_radio( array(
'id' => '_radiobutton',
'label' => 'Радиокнопки',
'class' => 'radio-field', // Произвольный класс поля
'style' => '', // Произвольные стили для поля
'wrapper_class' => 'wrap-radio', // Класс обертки поля
'desc_tip' => 'true', // Включение подсказки
'description' => 'Выберите значение',// Описение поля
'name' => 'radio-field', // Имя поля
'options' => array(
'one' => 'Один',
'two' => 'Два',
'three' => 'Три',
),
) );
Примерно тоже самое, что и селект, только внешний вид разный. Хотя селектом пользоваться иногда удобнее.
к содержаниюПроизвольное поле. Выбор товаров с поиском
<p class="form-field product_field_type">
<label for="product_field_type">Выбор товаров</label>
<select
id="product_field_type"
name="product_field_type[]"
class="wc-product-search"
multiple="multiple"
style="width: 50%;"
data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>"
data-action="woocommerce_json_search_products_and_variations"
data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = [];
$product_field_type_ids = get_post_meta( $post->ID, '_product_field_type_ids', true );
if ( ! empty( $product_field_type_ids ) ) {
$product_ids = array_map( 'absint', $product_field_type_ids );
}
if ( $product_ids ) {
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
echo sprintf(
'<option value="%s" %s>%s</option>',
esc_attr( $product_id ),
selected( true, true, false ),
esc_html( $product->get_formatted_name() )
);
}
}
?>
</select>
<span class="woocommerce-help-tip" data-tip="Тут можно указать какое-нибудь описание"></span>
</p>
Аналог поля на вкладке Сопутствующие Апсел или Кроссел. Вводите первые три буквы из названия товара и происходит автоматический поиск. Находит все товары, кроме текущего. Удобная вещь.
к содержаниюПроизвольная группа полей
<div class="options_group">
<h2><strong>Произвольная группа полей</strong></h2>
<p class="form-field custom_field_type">
<label for="custom_field_type">
<?php echo 'Размер в упаковке (mm)'; ?>
</label>
<span class="wrap">
<input
placeholder="Длина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_length"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_length', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Ширина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_width"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_width', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Высота"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_height"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_height', true ) ); ?>"
style="width: 15.75%;margin-right: 0;"/>
</span>
<span
class="description">
<?php echo esc_html( wc_help_tip( 'Введите размер товара в упаковке в формате ДхШхВ' ) ); ?>
</span>
</p>
</div>
Просто группа из трех полей. В данном случае, реальный пример для ввода дополнительных размеров, которое используется в одном из моих проектов.
к содержаниюПолный код со всеми видами полей, в том числе и произвольными
/**
* Полный код со всеми видами полей, в том числе и произвольными
*
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @author Artem Abramovich
*
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
function art_woo_add_custom_fields() {
global $product, $post;
echo '<div class="options_group">'; // Группировка полей.
// текстовое поле.
woocommerce_wp_text_input(
[
'id' => '_text_field',
'label' => __( 'Текстовое поле', 'woocommerce' ),
'placeholder' => 'Текстовое поле',
'desc_tip' => 'true',
'custom_attributes' => [ 'required' => 'required' ],
'description' => __( 'Введите здесь значение поля', 'woocommerce' ),
]
);
// Цифровое поле.
woocommerce_wp_text_input(
[
'id' => '_number_field',
'label' => __( 'Цифровое поле', 'woocommerce' ),
'placeholder' => 'Ввод чисел',
'description' => __( 'Вводятся только числа', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => [
'step' => 'any',
'min' => '0',
],
]
);
// Тектовая область.
woocommerce_wp_textarea_input(
[
'id' => '_textarea', // Идентификатор поля.
'label' => 'Область текста', // Заголовок поля.
'placeholder' => 'Ввод текста', // Надпись внутри поля.
'class' => 'textarea-field', // Произвольный класс поля.
'style' => 'width: 70%; background:red', // Произвольные стили для поля.
'wrapper_class' => 'wrap-textarea', // Класс обертки поля.
'desc_tip' => 'true', // Включение подсказки.
'description' => 'Здесь можно что-нибудть вводить', // Описание поля.
'name' => 'textarea-field', // Имя поля.
'rows' => '5', // Высота поля в строках текста.
'col' => '10', // Ширина поля в символах.
]
);
// Выбор значения.
woocommerce_wp_select(
[
'id' => '_select',
'label' => 'Выпадающий список',
'options' => [
'one' => __( 'Option 1', 'woocommerce' ),
'two' => __( 'Option 2', 'woocommerce' ),
'three' => __( 'Option 3', 'woocommerce' ),
],
]
);
// Чекбокс.
woocommerce_wp_checkbox(
[
'id' => '_checkbox',
'wrapper_class' => 'show_if_simple',
'label' => 'Чекбокс',
'description' => 'Выбери меня!',
]
);
// Радиокнопки.
woocommerce_wp_radio(
[
'id' => '_radiobutton',
'label' => 'Радиокнопки',
'class' => 'radio-field', // Произвольный класс поля.
'style' => '', // Произвольные стили для поля.
'wrapper_class' => 'wrap-radio', // Класс обертки поля.
'desc_tip' => 'true', // Включение подсказки.
'description' => 'Выберите значение', // Описение поля.
'name' => 'radio-field', // Имя поля.
'options' => [
'one' => 'Один',
'two' => 'Два',
'three' => 'Три',
],
]
);
// Скрытое поле.
woocommerce_wp_hidden_input(
[
'id' => '_hidden_field',
'value' => 'hidden_value',
]
);
echo '</div>'; // Закрывающий тег Группировки полей
// Выбор товаров.
?>
<p class="form-field product_field_type">
<label for="product_field_type">Выбор товаров</label>
<select
id="product_field_type"
name="product_field_type[]"
class="wc-product-search"
multiple="multiple"
style="width: 50%;"
data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>"
data-action="woocommerce_json_search_products_and_variations"
data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = [];
$product_field_type_ids = get_post_meta( $post->ID, '_product_field_type_ids', true );
if ( ! empty( $product_field_type_ids ) ) {
$product_ids = array_map( 'absint', $product_field_type_ids );
}
if ( $product_ids ) {
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
echo sprintf(
'<option value="%s" %s>%s</option>',
esc_attr( $product_id ),
selected( true, true, false ),
esc_html( $product->get_formatted_name() )
);
}
}
?>
</select>
<span class="woocommerce-help-tip" data-tip="Тут можно указать какое-нибудь описание"></span>
</p>
<div class="options_group">
<h2><strong>Произвольная группа полей</strong></h2>
<p class="form-field custom_field_type">
<label for="custom_field_type">
<?php echo 'Размер в упаковке (mm)'; ?>
</label>
<span class="wrap">
<input
placeholder="Длина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_length"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_length', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Ширина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_width"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_width', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Высота"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_height"
value="<?php echo esc_attr( get_post_meta( $post->ID, '_pack_height', true ) ); ?>"
style="width: 15.75%;margin-right: 0;"/>
</span>
<span
class="description">
<?php echo esc_html( wc_help_tip( 'Введите размер товара в упаковке в формате ДхШхВ' ) ); ?>
</span>
</p>
</div>
<?php
}
add_action( 'woocommerce_product_options_general_product_data', 'art_woo_add_custom_fields' );
Если коротко, то можно создать любое поле. Все зависит только от ваших желаний и умений.
к содержаниюСохранение полей
Для сохранения полей используем хук woocommerce_process_product_meta
.
Дальше просто — выдергиваем нужное значение из переменной $_POST, если там что-то есть то записываем в поле. Подробно расписывать не буду, вроде и так понятно и весь код откомментирован.
/**
* Сохранение данных произвольльных полей методами ядра
*
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @author Artem Abramovich
*
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
function art_woo_custom_fields_save( $post_id ) {
// Сохранение текстового поля.
$woocommerce_text_field = $_POST['_text_field'];
if ( ! empty( $woocommerce_text_field ) ) {
update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) );
}
// Сохранение цифрового поля.
$woocommerce_number_field = $_POST['_number_field'];
if ( ! empty( $woocommerce_number_field ) ) {
update_post_meta( $post_id, '_number_field', esc_attr( $woocommerce_number_field ) );
}
// Сохранение области тектса.
$woocommerce_textarea = $_POST['textarea-field'];
if ( ! empty( $woocommerce_textarea ) ) {
update_post_meta( $post_id, '_textarea', esc_html( $woocommerce_textarea ) );
}
// Сохранение выпадающего списка.
$woocommerce_select = $_POST['_select'];
if ( ! empty( $woocommerce_select ) ) {
update_post_meta( $post_id, '_select', esc_attr( $woocommerce_select ) );
}
// Сохранение радиокнопок.
$woocommerce_radio = $_POST['radio-field'];
if ( ! empty( $woocommerce_radio ) ) {
update_post_meta( $post_id, '_radiobutton', esc_attr( $woocommerce_radio ) );
}
// Сохранение чекбоксов.
$woocommerce_checkbox = isset( $_POST['_checkbox'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_checkbox', $woocommerce_checkbox );
// Сохранение группы произвольных полей.
$woocommerce_pack_length = $_POST['_pack_length'];
if ( ! empty( $woocommerce_pack_length ) ) {
update_post_meta( $post_id, '_pack_length', esc_attr( $woocommerce_pack_length ) );
}
$woocommerce_pack_width = $_POST['_pack_width'];
if ( ! empty( $woocommerce_pack_width ) ) {
update_post_meta( $post_id, '_pack_width', esc_attr( $woocommerce_pack_width ) );
}
$woocommerce_pack_height = $_POST['_pack_height'];
if ( ! empty( $woocommerce_pack_height ) ) {
update_post_meta( $post_id, '_pack_height', esc_attr( $woocommerce_pack_height ) );
}
// Hidden Field
$woocommerce_hidden_field = $_POST['_hidden_field'];
if ( ! empty( $woocommerce_hidden_field ) ) {
update_post_meta( $post_id, '_hidden_field', esc_attr( $woocommerce_hidden_field ) );
}
// Сохранение произвольного поля по выбору товаров с поиском
if ( ! empty( $_POST['product_field_type'] ) && isset( $_POST['product_field_type'] ) ) {
// Проверяем данные, если они существуют и не пустые, то записываем данные в поле
update_post_meta( $post_id, '_product_field_type_ids', array_map( 'absint', (array) $_POST['product_field_type'] ) );
} else {
// Иначе удаляем созданное поле из бд
delete_post_meta( $post_id, '_product_field_type_ids' );
}
}
add_action( 'woocommerce_process_product_meta', 'art_woo_custom_fields_save', 10 );
Другой способ сохранения полей через методы самого WooCommerce.
/**
* Сохранение данных произвольльных полей методами WooCommerce
*
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @author Artem Abramovich
*
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
add_action( 'woocommerce_process_product_meta', 'art_woo_custom_fields_save', 10 );
function art_woo_custom_fields_save( $post_id ) {
// Вызываем объект класса
$product = wc_get_product( $post_id );
// Сохранение текстового поля
$text_field = isset( $_POST['_text_field'] ) ? sanitize_text_field( $_POST['_text_field'] ) : '';
$product->update_meta_data( 'special_price', $text_field );
// Сохранение цифрового поля
$number_field = isset( $_POST['_number_field'] ) ? sanitize_text_field( $_POST['_number_field'] ) : '';
$product->update_meta_data( '_number_field', $number_field );
// Сохранение области тектса
$textarea_field = isset( $_POST['textarea-field'] ) ? sanitize_text_field( $_POST['textarea-field'] ) : '';
$product->update_meta_data( '_textarea', $textarea_field );
// Сохранение выпадающего списка
$select_field = isset( $_POST['_select'] ) ? sanitize_text_field( $_POST['_select'] ) : '';
$product->update_meta_data( '_textarea', $select_field );
// Сохранение радиокнопок
$radio_field = isset( $_POST['radio-field'] ) ? sanitize_text_field( $_POST['radio-field'] ) : '';
$product->update_meta_data( '_radiobutton', $radio_field );
// Сохранение чекбоксов
$checkbox_field = isset( $_POST['_checkbox'] ) ? 'yes' : 'no';
$product->update_meta_data( '_checkbox', $checkbox_field );
// Сохранение группы произвольных полей
$pack_length = isset( $_POST['_pack_length'] ) ? sanitize_text_field( $_POST['_pack_length'] ) : '';
$pack_width = isset( $_POST['_pack_width'] ) ? sanitize_text_field( $_POST['_pack_width'] ) : '';
$pack_height = isset( $_POST['_pack_height'] ) ? sanitize_text_field( $_POST['_pack_height'] ) : '';
$product->update_meta_data( 'pack_length', $pack_length );
$product->update_meta_data( 'pack_width', $pack_width );
$product->update_meta_data( 'pack_height', $pack_height );
// Сохранение скрытого поля
$hidden_field = isset( $_POST['_hidden_field'] ) ? sanitize_text_field( $_POST['_hidden_field'] ) : '';
$product->update_meta_data( '_hidden_field', $hidden_field );
// Сохраняем все значения
$product->save();
}
Код рабочий. Идеи по улучшению, пишите в комментариях.
Вот так должно получиться в итоге
к содержаниюВывод полей
Вывод значений производится через штатную функцию самого WordPress get_post_meta()
. Примерно так
// Отображение значения настраиваемого поля
echo get_post_meta ( $post->ID , 'my-field-slug', true );
А конкретно по примерным полям из статьи, то можно вывод подвесить в нужном месте карточки товара.
Тоже самое, только используя методы WooCommerce
// Отображение значения настраиваемого поля
echo $product->get_meta( 'special_price', true );
где $product - объект товара
// Объект товара можно получить так
$product = wc_get_product();
к содержанию
Перед кнопкой Добавить в корзину
Выведем текстовое, цифровое и область текста.
Самый простой вариант
add_action( 'woocommerce_before_add_to_cart_form', 'art_get_text_field_before_add_card' );
function art_get_text_field_before_add_card() {
global $post;
echo get_post_meta( $post->ID, '_text_field', true );
echo get_post_meta( $post->ID, '_number_field', true );
echo get_post_meta( $post->ID, '_textarea', true );
}
Тоже самое, только используя методы WooCommerce
add_action( 'woocommerce_before_add_to_cart_form', 'art_get_text_field_before_add_card' );
function art_get_text_field_before_add_card() {
$product = wc_get_product();
echo $product->get_meta( '_text_field', true );
echo $product->get_meta( '_number_field', true );
echo $product->get_meta( '_textarea', true );
}
Вариант с проверками и форматированием
add_action( 'woocommerce_before_add_to_cart_form', 'art_get_text_field_before_add_card' );
function art_get_text_field_before_add_card() {
global $post, $product;
$text_field = get_post_meta( $post->ID, '_text_field', true );
$num_field = get_post_meta( $post->ID, '_number_field', true );
$textarea_field = get_post_meta( $post->ID, '_textarea', true );
if ( $text_field ) {
?>
<div class="text-field">
<strong>Текстовое поле: </strong>
<?php echo $text_field; ?>
</div>
<?php }
if ( $num_field ) { ?>
<div class="number-field">
<strong>Цифровое поле: </strong>
<?php echo $num_field; ?>
</div>
<?php }
if ( $textarea_field ) { ?>
<div class="textarea-field">
<strong>Область текста: </strong>
<?php echo $textarea_field; ?>
</div>
<?php
}
}
Тоже самое, только используя методы WooCommerce
add_action( 'woocommerce_before_add_to_cart_form', 'art_get_text_field_before_add_card' );
function art_get_text_field_before_add_card() {
// Вызываем объект товара
$product = wc_get_product();
// Записываем значения полей в переменные
$text_field = $product->get_meta( '_text_field', true );
$num_field = $product->get_meta( '_number_field', true );
$textarea_field = $product->get_meta( '_textarea', true );
// Выводим значения полей
if ( $text_field ) :
?>
<div class="text-field">
<strong>Текстовое поле: </strong>
<?php echo $text_field; ?>
</div>
<?php endif;
if ( $num_field ) : ?>
<div class="number-field">
<strong>Цифровое поле: </strong>
<?php echo $num_field; ?>
</div>
<?php endif;
if ( $textarea_field ) : ?>
<div class="textarea-field">
<strong>Область текста: </strong>
<?php echo $textarea_field; ?>
</div>
<?php
endif;
}
Вывод полей с форматированием будет выглядеть так
к содержаниюПосле кнопки Добавить в корзину
Выводим заначения селекта, радиокнопки и чека. Данные поля работают по условию и выводят что одно.
Пример кода (написано на коленке для примера, но все работает)
add_action( 'woocommerce_after_add_to_cart_form', 'art_get_text_field_after_add_card' );
function art_get_text_field_after_add_card() {
global $post, $product;
$select_field = get_post_meta( $post->ID, '_select', true );
$radio_field = get_post_meta( $post->ID, '_radiobutton', true );
$check_field = get_post_meta( $post->ID, '_checkbox', true );
if ( $select_field ) {
echo '<div><strong>Вывод значения при выборе в селекте</strong>';
switch ( $select_field ) {
case 'one':
echo '<div>Первая опция селекта</div>';
break;
case 'two':
echo '<div>Вторая опция селекта</div>';
break;
case 'three':
echo '<div>Третья опция селекта</div>';
break;
}
echo '</div>';
}
if ( $radio_field ) {
echo '<div><strong>Вывод значения при выборе радиокнопки</strong>';
switch ( $radio_field ) {
case 'one':
echo '<div>Значение первой радиокнопки</div>';
break;
case 'two':
echo '<div>Значение второй радиокнопки</div>';
break;
case 'three':
echo '<div>Значение третьей радиокнопки</div>';
break;
}
echo '</div>';
}
if ( $check_field ) {
echo '<div><strong>Срабатывание чекбокса</strong>';
if ( $check_field === 'yes' ) {
echo '<div>Чек выбран</div>';
} else {
echo '<div>Чек НЕ выбран</div>';
}
echo '</div>';
}
}
В итоге получаем.
Были такие значения в админке
И получаем, такой вывод
Изменяем значения
Получаем
к содержаниюВывод группы полей во вкладке Дополнительная информация
Используем хук woocommerce_product_additional_information
и получаем такой код
add_action( 'woocommerce_product_additional_information', 'art_get_fields_tab_additional_information' );
function art_get_fields_tab_additional_information() {
global $post;
$length_field = get_post_meta( $post->ID, '_pack_length', true );
$width_field = get_post_meta( $post->ID, '_pack_width', true );
$height_field = get_post_meta( $post->ID, '_pack_height', true );
?>
<table class="shop_attributes_addon">
<tbody>
<tr>
<th>Размеры упаковки, <?php echo get_option( 'woocommerce_dimension_unit' );?></th>
<td class="product_length"><?php echo $length_field; ?></td>
<td class="product_width"><?php echo $width_field; ?></td>
<td class="product_height"><?php echo $height_field; ?></td>
</tr>
</tbody>
</table>
<?php
}
Вот так это выглядит
к содержаниюВывод выбранных товаров перед вкладками с информацией
Ну и самое вкусное: выведем список выбранных товаров перед вкладками. Зачем так делать не занаю, но вдруг кому пригодиться.
Итак, наше поле возвращает нам массив ID товаров, значит нам достаточно запихать сей массив в функцию wc_get_products
и вывести нужные товары. Примерно так, выводим список заголовков выбранных товаров.
add_action( 'woocommerce_single_product_summary', 'art_get_list_product', 65 );
function art_get_list_product() {
global $post;
$product_field_id = get_post_meta( $post->ID, '_product_field_type_ids', true );
$product_lists = wc_get_products( array(
'include' => $product_field_id,
));
echo '<ul>';
foreach ($product_lists as $list){
echo '<li><a href="'. get_permalink($list->get_ID()) .'">'. $list->get_formatted_name() .'</a></li>';
}
echo '</ul>';
}
Код не идеальный, надо конечно и проверки сделать, но все работает. Получим такой вот список выбранных товаров
к содержаниюВывод значения полей на страницах архивов
Зачем выводить эти данные в ленте товаров не знаю, но вдруг нужно. Для вывода на витрине, странице рубрик, похожих и т.д. требуется использовать соответствующие хуки. Для примера
Перед ценой
add_action( 'woocommerce_after_shop_loop_item_title', 'artabr_add_field_before_price', 9 );
function artabr_add_field_before_price() {
global $post, $product;
$text_field = get_post_meta( $post->ID, '_text_field', true );
$num_field = get_post_meta( $post->ID, '_number_field', true );
$textarea_field = get_post_meta( $post->ID, '_textarea', true );
if ( $text_field ) {
?>
<div class="text-field">
<strong>Текстовое поле: </strong>
<?php echo $text_field; ?>
</div>
<?php }
if ( $num_field ) { ?>
<div class="number-field">
<strong>Цифровое поле: </strong>
<?php echo $num_field; ?>
</div>
<?php }
if ( $textarea_field ) { ?>
<div class="textarea-field">
<strong>Область текста: </strong>
<?php echo $textarea_field; ?>
</div>
<?php
}
}
После цены
add_action( 'woocommerce_after_shop_loop_item_title', 'artabr_add_field_after_price', 11 );
function artabr_add_field_after_price() {
global $post, $product;
$text_field = get_post_meta( $post->ID, '_text_field', true );
$num_field = get_post_meta( $post->ID, '_number_field', true );
$textarea_field = get_post_meta( $post->ID, '_textarea', true );
if ( $text_field ) {
?>
<div class="text-field">
<strong>Текстовое поле: </strong>
<?php echo $text_field; ?>
</div>
<?php }
if ( $num_field ) { ?>
<div class="number-field">
<strong>Цифровое поле: </strong>
<?php echo $num_field; ?>
</div>
<?php }
if ( $textarea_field ) { ?>
<div class="textarea-field">
<strong>Область текста: </strong>
<?php echo $textarea_field; ?>
</div>
<?php
}
}
Хуков много, можно по разному вывести при необходимости.
к содержаниюГруппировка произвольных полей на произвольной вкладке
Любая вкладка в метабоксе WooCommerce состоит из двух частей:
- сама вкладка
- содержание вкладки
Создание произвольной вкладки
Все вкладки формируются в классе WC_Meta_Box_Product_Data
. Для добавления новой вкладки воспользуемся фильтром woocommerce_product_data_tabs
.
/**
* Создание произвольной вкладки
*
* @param array $tabs Массив вкладок.
*
* @return array
*
* @author Artem Abramovich
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
function art_added_tabs( array $tabs ): array {
$tabs['special_panel'] = [
'label' => 'Произвольный', // название вкладки.
'target' => 'special_panel_product_data', // идентификатор вкладки.
'class' => [ 'hide_if_grouped' ], // классы управления видимостью вкладки в зависимости от типа товара.
'priority' => 5, // приоритет вывода.
];
return $tabs;
}
add_filter( 'woocommerce_product_data_tabs', 'art_added_tabs', 10, 1 );
Изменяя атрибут priority
можно изменять положение вкладки в общем списке. Чем больше значение, тем ниже вкладка будет располагаться.
Атрибут class
позволяет добавить к вкладке любой класс. Но используя стандартные классы WooCommerce, можно управлять поведением вкладки.
Все классы для управления поведением
show_if_simple
— показывать только для простых товаровshow_if_variable
— показывать только для вариативных товаровshow_if_grouped
— показывать только для сгруппированных товаровshow_if_external
— показывать только для внешних товаровhide_if_simple
— скрывать для простых товаровhide_if_variable
— скрывать для вариативных товаровhide_if_grouped
— скрывать для сгруппированных товаровhide_if_external
— скрывать для внешних товаров
Изменение иконки вкладки
Для иконки можно использовать что угодно. SVG, просто картинки или существующие шрифты Dashicons или набор самого WooCommerce.
Для изменения иконки достаточно добавить немного стилей:
/**
* Добавление иконки для произвольной вкладки
*
* @author Artem Abramovich
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
function art_added_tabs_icon() {
?>
<style>
#woocommerce-coupon-data ul.wc-tabs li.special_panel_options a::before,
#woocommerce-product-data ul.wc-tabs li.special_panel_options a::before,
.woocommerce ul.wc-tabs li.special_panel_options a::before {
font-family: WooCommerce;
content: "\e03d";
}
</style>
<?php
}
add_action( 'admin_footer', 'art_added_tabs_icon' );
к содержанию
Добавление содержимого вкладки
Для добавления содержимого используется тот же принцип что и при добавлении на любую другую вкладку. Только используется хук woocommerce_product_data_panels
.
Для примера добавим текстовое поле и произвольную группу полей.
/**
* Вывод данных произвольльных полей на произвольной вкладке
*
* @testedwith WooCommerce 5.5
* @verphp 7.0
* @author Artem Abramovich
*
* @source https://wpruse.ru/woocommerce/custom-fields-in-products/
*/
function art_added_tabs_panel() {
$product = wc_get_product();
?>
<div id="special_panel_product_data" class="panel woocommerce_options_panel">
<div class="options_group">
<?php
$arg = [
'id' => 'special_price',
'label' => 'Специальная цена',
'data_type' => 'price',
'desc_tip' => true,
'description' => 'Укажите значение специальной цены',
];
woocommerce_wp_text_input( $arg );
?>
</div>
<div class="options_group">
<h2><strong>Произвольная группа полей</strong></h2>
<p class="form-field custom_field_type">
<label for="custom_field_type"><?php echo 'Размер в упаковке (mm)'; ?></label>
<span class="wrap">
<input
placeholder="Длина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_length"
value="<?php echo esc_attr( $product->get_meta( '_pack_length', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Ширина"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_width"
value="<?php echo esc_attr( $product->get_meta( '_pack_width', true ) ); ?>"
style="width: 15.75%;margin-right: 2%;"/>
<input
placeholder="Высота"
class="input-text wc_input_decimal"
size="6"
type="text"
name="_pack_height"
value="<?php echo esc_attr( $product->get_meta( '_pack_height', true ) ); ?>"
style="width: 15.75%;margin-right: 0;"/>
</span>
<span class="description"><?php echo esc_html( wc_help_tip( 'Введите размер товара в упаковке в формате ДхШхВ' ) ); ?></span>
</p>
</div>
</div>
<?php
}
add_action( 'woocommerce_product_data_panels', 'art_added_tabs_panel' );
Получаем такой вид
Важно! ID обертки полей вкладки должен соответствовать атрибуту target
, который указан при регистрации вкладки.
А дальше уже стандартно. Сохраняем значения и выводим там где требуется.
Для сохранения и вывода рекомендую использовать методы самого WooCommerce.
к содержаниюКейс. Дополнительные поля на вкладке «Основные»
Задача
- Добавить дополнительные поля на вкладке Основные
- Вывести значения полей в виде кнопки на странице товара и страницах архивов
Решение
Первое. Создаем поля
Это самое простое. Нужна кнопка, которую можно сформировать из двух полей:
- надпись на кнопке;
- ссылка на кнопке.
/*
* Добавляем поля
*/
add_action( 'woocommerce_product_options_general_product_data', 'demolink_woo_add_custom_fields' );
function demolink_woo_add_custom_fields() {
echo '<div class="options_group">';// Группировка полей
// текстовое поле
woocommerce_wp_text_input( array(
'id' => '_demo_name',
'label' => __( 'Надпись на кнопке', 'woocommerce' ),
'placeholder' => 'Надпись',
'desc_tip' => 'true',
'description' => __( 'Укажите надпись', 'woocommerce' ),
) );
// текстовое поле
woocommerce_wp_text_input( array(
'id' => '_demo_link',
'label' => __( 'Ссылка на демо', 'woocommerce' ),
'placeholder' => 'Ссылка',
'desc_tip' => 'true',
'data_type' => 'url',
'description' => __( 'Введите ссылку', 'woocommerce' ),
) );
echo '</div>';
}
/*
* Сохраняем значение полей
*/
add_action( 'woocommerce_process_product_meta', 'demolink_woo_custom_fields_save', 10 );
function demolink_woo_custom_fields_save( $post_id ) {
update_post_meta( $post_id, '_demo_link', esc_url( $_POST['_demo_link'] ) );
update_post_meta( $post_id, '_demo_name', esc_attr( $_POST['_demo_name'] ) );
}
к содержанию
Второе. Вывод полей
Для вывода значений на странице товара используем хук woocommerce_before_add_to_cart_form
, на страницах архивов — woocommerce_after_shop_loop_item
с приоритетом.
add_action( 'woocommerce_after_shop_loop_item', 'demolink_get_button', 5 );
add_action( 'woocommerce_before_add_to_cart_form', 'demolink_get_button' );
function demolink_get_button() {
global $post, $product;
$demo_link = get_post_meta( $post->ID, '_demo_link', true );
$demo_name = get_post_meta( $post->ID, '_demo_name', true );
if ( $demo_link ) {
$demo_btn = '<div class="demo-link">';
$demo_btn .= '<a href="' . $demo_link . '" class="demo-link-button button alt" target="_blank">' . $demo_name . '</a>';
$demo_btn .= '</div>';
echo $demo_btn;
}
}
к содержанию
Третье. Результат
к содержаниюКейс. Произвольное текстовое поле с редактором TinyMCE
Задача
- создать произвольное текстовое поле с редактором TinyMCE
- вывести значение поля во вкладке «Детали» на странице товара
Решение
к содержаниюПервое. Создаем новое поле
add_action( 'woocommerce_product_options_general_product_data', 'art_woo_add_custom_fields' );
function art_woo_add_custom_fields() {
global $product, $post;
?>
<div class="options_group">
<h2><strong>Дополнительное описание с редактором</strong></h2>
<?php
wp_editor(get_post_meta( $post->ID, '_custom_desc', true ), 'custom_desc', array(
'wpautop' => 1,
'media_buttons' => 1,
'textarea_name' => 'custom_desc',
'textarea_rows' => 5,
'tabindex' => null,
'editor_css' => '<style>.quicktags-toolbar, .wp-editor-tools, .wp-editor-wrap, .wp-switch-editor {padding: 5px 10px;}</style>',
'editor_class' => 'form-field',
'teeny' => 0,
'dfw' => 0,
'tinymce' => 1,
'quicktags' => 1,
'drag_drop_upload' => false
) );
?>
</div>
<?php
}
add_action( 'woocommerce_process_product_meta', 'art_woo_custom_fields_save', 10 );
function art_woo_custom_fields_save( $post_id ) {
// Сохранение области тектса
$woocommerce_textarea = $_POST['custom_desc'];
if ( ! empty( $woocommerce_textarea ) ) {
update_post_meta( $post_id, '_custom_desc', $woocommerce_textarea );
}
}
к содержанию
Второе. Выводим значение
add_action( 'woocommerce_product_additional_information', 'art_get_fields_tab_additional_information' );
function art_get_fields_tab_additional_information() {
global $post;
$custom_desc= get_post_meta( $post->ID, '_custom_desc', true );
?>
<div class="shop_attributes_addon">
<p>Дополнительное описание</p>
<p><?php echo $custom_desc; ?></p>
</div>
<?php
}
Третье. Результат
Заключение
В статье разобрал создание и вывод различных типов полей для простых товаров в Woocommerce. Как с использованием штатного API так и создание своих собственных полей и групп полей. Разжевал все очень подробно. Весь код в статье рабочий и проверенный.
На этом все, если остались вопросы, пишите в комментариях, не забудьте поделиться статьей в соцсетях. Всем успехов, пока-пока!