Добавление произвольных полей в товарах Woocommerce. Большая инструкция

Приветствую! В Woocommerce уже есть очень мощный API, который позволяет добавлять много разных вкусных решений. В этой статье разберем, как добавлять произвольные поля к простым товарам.

Внимание!
Данная статья предназначена в первую очередь для разработчиков и тех, кто хочет подробнее разобраться. Если вы не любите ковыряться в коде, а поля все же нужны, то проще воспользоваться готовым решением. Например, плагином WooCommerce Custom Product Data Fields или WC Factory Fields
Внимание!
Весь код необходимо добавлять в файл functions.php или например пустой плагин. Прежде чем, вносить какие либо изменения, сделайте бекап сайта.

Продолжим. Вот такая штука у нас получиться.

 

Произвольные поля в товарах Woocommerce
Результат добавления полей
к содержанию

Теория. Необходимые хуки и функции

В Woocomerce на любой чих найдется нужный акшион или фильтр (то, что называется хуки). Потому и мы будем использовать нужные нам хуки.

Нужные хуки

Хуки для добавление полей на вкладку

Для добавления полей в нужную вкладку, в нашем случае это вкладка «Основные» используется хук

woocommerce_product_options_general_product_data

Если необходимо подключить поле в другой вкладке, то можно использовать такие хуки

// Вкладка Доставка
woocommerce_product_options_shipping
// Вкладка Сопутствующие
woocommerce_product_options_related
// Вкладка Запасы
woocommerce_product_options_inventory_product_data
// Вкладка Атрибуты
woocommerce_product_options_attributes
// Вкладка Дополнительно
woocommerce_product_options_advanced
к содержанию

Хуки для сохранения значения полей

Для сохранения наших полей будем использовать хук

woocommerce_process_product_meta

Это базовый хук, который позволяет сохранять значения произвольных полей для простых товаров

Хуки для вывода полей

Поля — дело индивидуальное для каждого товара. А товар в 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.
Внимание! Это относиться ко всем типам полей. Напомню, в глобальную переменную $_POST приходят значения поля name и при изменении параметра name на собственный, ловить надо именно это значение, а не id Иначе, просто не сохраниться значение поля.
к содержанию

Выпадающий список. 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&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
      <?php
      $product_field_type_ids = get_post_meta( $post->ID, '_product_field_type_ids', true );
      $product_ids = ! empty( $product_field_type_ids ) && isset($product_field_type_ids) ? array_map( 'absint',  $product_field_type_ids ) : array();
      if ( $product_ids ) {
         foreach ( $product_ids as $product_id ) {
            $product      = wc_get_product( $product_id );
            $product_name = $product->get_formatted_name();
            echo '<option value="' . esc_attr( $product_id ) . '" ' . selected(true, true, false )  . '>' .
                 esc_html( $product->get_formatted_name() ) . '</option>';
         }
      }
      ?>
   </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 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 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 get_post_meta( $post->ID, '_pack_height', true ); ?>"
      style="width: 15.75%;margin-right: 0;"/>
</span> <span
         class="description"><?php echo wc_help_tip( 'Введите размер товара в упаковке в формате ДхШхВ' ); ?></span>
   </p>
</div>

Просто группа из трех полей. В данном случае, реальный пример для ввода дополнительных размеров, которое используется в одном из моих проектов.

к содержанию

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

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">';// Группировка полей
   // текстовое поле
   woocommerce_wp_text_input( array(
      'id'                => '_text_field',
      'label'             => __( 'Текстовое поле', 'woocommerce' ),
      'placeholder'       => 'Текстовое поле',
      'desc_tip'          => 'true',
      'custom_attributes' => array( 'required' => 'required' ),
      'description'       => __( 'Введите здесь значение поля', 'woocommerce' ),
   ) );
   // цифровое поле
   woocommerce_wp_text_input( array(
      'id'                => '_number_field',
      'label'             => __( 'Цифровое поле', 'woocommerce' ),
      'placeholder'       => 'Ввод чисел',
      'description'       => __( 'Вводятся только числа', 'woocommerce' ),
      'type'              => 'number',
      'custom_attributes' => array(
         'step' => 'any',
         'min'  => '0',
      ),
   ) );
   // Тектовая область
   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', //Ширина поля в символах.
   ) );
   // Выбор значения
   woocommerce_wp_select( array(
      'id'      => '_select',
      'label'   => 'Выпадающий список',
      'options' => array(
         'one'   => __( 'Option 1', 'woocommerce' ),
         'two'   => __( 'Option 2', 'woocommerce' ),
         'three' => __( 'Option 3', 'woocommerce' ),
      ),
   ) );
   // Чекбокс
   woocommerce_wp_checkbox( array(
      'id'            => '_checkbox',
      'wrapper_class' => 'show_if_simple',
      'label'         => 'Чекбокс',
      'description'   => 'Выбери меня!',
   ) );
   // Радиокнопки
   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' => 'Три',
      ),
   ) );
   // скрытое поле
   woocommerce_wp_hidden_input( array(
      'id'    => '_hidden_field',
      'value' => 'hidden_value',
   ) );
   // Выбор товаров
   ?>
   <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&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
         <?php
         $product_field_type_ids = get_post_meta( $post->ID, '_product_field_type_ids', true );
         $product_ids = ! empty( $product_field_type_ids ) && isset($product_field_type_ids) ? array_map( 'absint',  $product_field_type_ids ) : array();
         if ( $product_ids ) {
            foreach ( $product_ids as $product_id ) {
               $product      = wc_get_product( $product_id );
               $product_name = $product->get_formatted_name();
               echo '<option value="' . esc_attr( $product_id ) . '" ' . selected(true, true, false )  . '>' .
                    esc_html( $product->get_formatted_name() ) . '</option>';
            }
         }
         ?>
      </select><span class="woocommerce-help-tip" data-tip="Тут можно указать какое-нибудь описание"></span>
   </p>
   </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 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 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 get_post_meta( $post->ID, '_pack_height', true ); ?>"
         style="width: 15.75%;margin-right: 0;"/>
   </span> <span
            class="description"><?php echo wc_help_tip( 'Введите размер товара в упаковке в формате ДхШхВ' ); ?></span>
      </p>
   </div>
   <?php
}

Если коротко, то можно создать любое поле. Все зависит только от ваших желаний и умений.

к содержанию

Сохранение полей

Повторюсь. Для сохранения полей используем хук woocommerce_process_product_meta. А дальше все просто — выдергиваем нужное значение из переменной $_POST, если там что-то есть то записываем в поле. Подробно расписывать не буду, вроде и так понятно и весь код откомментирован.

add_action( 'woocommerce_process_product_meta', 'art_woo_custom_fields_save', 10 );
function art_woo_custom_fields_save( $post_id ) {
   // Сохранение текстового поля
   $woocommerce_text_field = $_POST['_text_field'];
   if ( $woocommerce_text_field ) {
      update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) );
   }
   // Сохранение цифрового поля
   $woocommerce_number_field = $_POST['_number_field'];
   if ( $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 ( $woocommerce_select ) {
      update_post_meta( $post_id, '_select', esc_attr( $woocommerce_select ) );
   }
   // Сохранение радиокнопок
   $woocommerce_radio = $_POST['radio-field'];
   if ( $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 ( $woocommerce_pack_length ) {
      update_post_meta( $post_id, '_pack_length', esc_attr( $woocommerce_pack_length ) );
   }
   $woocommerce_pack_width = $_POST['_pack_width'];
   if ( $woocommerce_pack_width ) {
      update_post_meta( $post_id, '_pack_width', esc_attr( $woocommerce_pack_width ) );
   }
   $woocommerce_pack_height = $_POST['_pack_height'];
   if ( $woocommerce_pack_height ) {
      update_post_meta( $post_id, '_pack_height', esc_attr( $woocommerce_pack_height ) );
   }
   // Hidden Field
   $woocommerce_hidden_field = $_POST['_hidden_field'];
   if ( $woocommerce_hidden_field ) {
      update_post_meta( $post_id, '_hidden_field', esc_attr( $woocommerce_hidden_field ) );
   }
   // Сохранение произвольного поля по выбору товаров с поиском
   if (  isset( $_POST['product_field_type'] ) && !empty($_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');
   }
}

Код не идеальный, конечно, но рабочий. Есть идеи по улучшению, пишите в комментариях.

Вот так должно получиться в итоге

Произвольные поля в товарах Woocommerce

к содержанию

Вывод полей

Вывод значений производится через штатную функцию самого WordPress get_post_meta(). Примерно так

// Отображение значения настраиваемого поля
echo get_post_meta ( $ post->ID , 'my-field-slug  , 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;
	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 );

}
Вариант с проверками и форматированием
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_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

И получаем, такой вывод

Произвольные поля в товарах Woocommerce

Изменяем значения

Произвольные поля в товарах Woocommerce

Получаем

Произвольные поля в товарах Woocommerce

к содержанию

Вывод группы полей во вкладке Дополнительная информация

Используем хук 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
}

Вот так это выглядит

Произвольные поля в товарах Woocommerce

к содержанию

Вывод выбранных товаров перед вкладками с информацией

Ну и самое вкусное: выведем список выбранных товаров перед вкладками. Зачем так делать не занаю, но вдруг кому пригодиться.

Итак, наше поле возвращает нам массив 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>';
}

Код не идеальный, надо конечно и проверки сделать, но все работает. Получим такой вот список выбранных товаров

Произвольные поля в товарах Woocommerce

к содержанию

Вывод значения полей на страницах архивов

Зачем выводить эти данные в ленте товаров не знаю, но вдруг нужно. Для вывода на витрине, странице рубрик, похожих и т.д. требуется использовать соответствующие хуки. Для примера

Перед ценой

Вывод значений полей на страницах архивов

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.  Как с использованием штатного API так и создание своих собственных полей и групп полей. Разжевал все очень подробно. Весь код в статье рабочий и проверенный, хоть и не идеальный.

На этом все, если остались вопросы, пишите в комментариях, не забудьте поделиться статьей в соцсетях. Всем успехов, пока-пока!

87 комментариев
  • Данил

    02.10.2017

    А где можно посмотреть полный список хуков WooCommerce?

    • Артем

      02.10.2017

      Вопрос у вас… В документации, ссылка в статье есть. В Ву хуком не меньше чем в самом ВП, а может и больше. Проще определить нужный хук под конкретную задачу

      • Данил

        04.10.2017

        Например, можно ли добавить текст к заголовку товара в карточке товара?

        На сайте fototapeta.ru, все товары именованы порядковым номером (№ 235). Нужно, чтобы только в карточке товара добавлялось слово (Фотообои № 235).

          • Данил

            04.10.2017

            Круто, спасибо. Только пока не совсем разобрался как это работает, но подумаю еще

          • Артем

            04.10.2017

            Пожалуйста. Там не сложно. Код откомментировал. А так все просто отключаем исходный вывод и подключаем собственный

      • Spartak

        05.12.2017

        А подскажите, как найти ИМЯ (название) хука (чтобы удалить, запретить изменить и т.п.)
        Как пример: как мне узнать что за дополнительную информацию выводит хук ‘woocommerce_product_additional_information (как пример)
        (извиняюсь если путано пишу, но не знаю как сформулировать ) ))

        • Артем

          09.12.2017

          Я обычно ищу в коде Вукомерса на Гитхабе, потом просто код смотрю

          • Spartak

            09.12.2017

            А там по какому принципу смотрите, просто по «ключевому слову»?

          • Артем

            09.12.2017

            Просто поиском по репозиторию ищу в каком файле встречается нужный хук и как работает

  • Андрей

    06.10.2017

    Извиняюсь за оффтоп, подскажите какой плагин используете для выделения текста которое сразу под содержанием.

  • Александр

    08.10.2017

    Здравствуйте. Спасибо за интересную статью! Подскажите, как сделать произвольное поле, в которое будут вводится значения, и потом их можно будет выводить выпадающим списком на странице товара. Это примерно так же как и атрибуты, но у меня с ними проблемы при обновлении товаров.
    Пример:
    _https://image.prntscr.com/image/ZjkP40HAQhmo9KyKPJHOLA.png
    _https://image.prntscr.com/image/QV4-SUY-Tsqf7LrPL0wSsg.png

    • Артем

      09.10.2017

      Доброго! Ну также как в примерах, создаете произвольное поле с выбором а потом просто выводите в селекте. Только что селект должен передавать не понятно

  • Андрей

    23.10.2017

    Доброго времени суток, Король Worpdress на Yotube (не сарказм, дань уважения, смотрю все видосы и несмотря на то,что инфа знакома, нахожу для себя фишки)! Как сделать, чтобы на единичной карточке товара добавить еще товары (даже не знаю как сделать запрос в поиск). Чтобы получилось вот как на это сайте: вот есть карточка товара (офисная мебель) _https://prnt.sc/h0i1xp которая состоит из нескольких частей, задача в том, чтобы вывести эти отдельные части ниже по раздельности, чтобы человек мог собрать «консутруктор: _https://prnt.sc/h0i2lw еще ниже _https://prnt.sc/h0i2r1 еще ниже _https://prnt.sc/h0i2xm и т.д. Оставлю ссылку, чтобы Вы могли посмотреть, если что потом, можете ее удалить или весь коммент, после ответа :))) _http://www.prosmebel.ru/mebel-dlya-personala/biznes/5th-element Спасибо! p.s: Какие есть самые легкие решения?!

      • Андрей

        23.10.2017

        Благодарю за ответ, в том числе за оперативность! Я пробовал юзать его (платный плагин из указанного Вами в ответе), получается не очень с точки зрения визуального оформления. Подскажите пожалуйста, при помощи каких плагинов сделать так,чтобы было похоже как на карточке, которую прислал в вопросе, плиззз. Можно только список плагинов по порядку, в сети найду инструкции и т.п. В коде не шарю, только информация из Ваших уроков на Ютубе. Спасибо!

        • Андрей

          23.10.2017

          Еще есть версия: каким-то образом при помощи этого плагина advancedcustomfields (ACF plugin) сделать на карточках товара отдельные поля, в эти поля через шорткоды выводить необходимые товары (по айди, специальную категория создать и т.п.)?

        • Артем

          24.10.2017

          Плагинов вагон, только названий не подскажу, просто не знаю

  • Кирилл

    24.10.2017

    А как сделать так, что бы выводилось не просто текстовое поле а html . т.е.
    В админки вставляешь код через редактор (например таблицы), а на карточке товара выводится отформатированный текст

  • Кирилл

    24.10.2017

    так сказать еще одно woocommerce_short_description

    • Артем

      29.10.2017

      Ну так же, использовать textarea или простой инпут

  • Кирилл

    29.10.2017

    Если использовать простой textarea или простой инпут то тэги в кроказяблы превращаются.

    • Артем

      29.10.2017

      Логично, это для безопасности делается. На выходе надо использовать преобразование тегов, например функцией htmlspecialchars

  • Кирилл

    29.10.2017

    Да, я так делал…. Но возникает вопрос, как сделать так, что бы тэги сохранялись изначально правильно. т.е. заносились в ячейку правильно.

    • Артем

      30.10.2017

      Вообще, не рекомендуется теги в базу запихивать, но если сильно надо есть куча очищающих функций. Например wp_kses()
      А зачем вообще хтмл запихивать в базу?

  • Кирилл

    30.10.2017

    мне надо вывести на странице дополнительно 3 таба. В каждой вкладке будет разное содержимое в одном вкладке будет табличка, во второй слайдер, в 3-ей информация с заголовками и списками.
    проще всего эти данные вводить через редактор wp_editor().
    http://dvip.by/product/dver-steklo/ -пример страницы.
    Данный функционал я реализовал с помощью 3 (новых ) метабоксов, но мне бы хотелось что бы поля для вводов по типу wp_editor() были видны только при заполнении карточек товаров.
    Ну и вопрос немного не по теме… adblock с чего то начал блокировать главный слайдер.. С чем это может быть связано?

  • Дмитрий

    19.11.2017

    Здравствуйте. Спасибо. Большое спасибо за столь интересную и понятную статью. Скажите я правильно понимаю, что вот этот плагин _https://ru.wordpress.org/plugins/wc-fields-factory/ выполняет всё то о чём Вы выше рассказали?
    И ещё один вопрос. Вы в комментариях сказали: — «зачем вообще хтмл запихивать в базу?» а разве те же поля полного и краткого описания товара не отправляют в базу html код? И если, да то какая функция позволяет вставлять и выводить html код? Я понимаю, что наверное не очень грамотно формулирую свою мысль, поэтому поясню. Вот например есть функция _text_field она позволяет выводить текст, а какая функция позволяет выводить html ?

    • Артем

      09.12.2017

      Доброго! Да, этот плагин делает все то, что описано в статье.
      Формально отправляют, но делается все немного по другому. Та же функция и позволяет, просто дело в том, что впиливание хтмл напрямую — чревато, всегда надо очищать поля. Но теоретически можно и через то же поле выводить хтмл

  • Max Chabirg

    20.11.2017

    Артем, Чудо статья, Спасибо!
    А можно ли вывести данные параметры в фильтры, на равне с атрибутами (через стандартное Woocommerce «Фильтрация товаров по атрибутам»)? Очень не хватает фильтров с механикой чекбокса, и прочих функций.

    • Артем

      09.12.2017

      Пожалуйста! Теоретически, все возможно, но в конкретно в этот виджет не получиться, проще новый виджет написать.

  • Oleg

    06.12.2017

    Добрый день.
    А можно ли зарегистрировать таксономию новых меток для товаров и затем выводить эти поля в цикле на вкладке товара «Основные» и сохранять эти данные. И правильно так вообще делать?

    • Артем

      09.12.2017

      Конечно можно, Вукоммерс использует весь функционал Вордпресса

  • Олег

    12.12.2017

    Привет. Спасибо за статью.
    Столкнулся с небольшими трудностями:
    Не сохраняет поля пустыми в админке, после нажатия кнопки «Обновить».
    Мне надо, чтобы в карточке не отображались те поля которые не заполнены.

    • Артем

      13.12.2017

      Привет! Раз не сохраняет, значит есть условие для этого, например, если в нумерованном типе указать что значение может быть только больше нуля, поле пустым и не будет сохраняться

  • Край

    13.12.2017

    Спасибо за статью!
    А можно ли как-то к action добавить свое условие, например что бы он выводил товары только из определенной категории?
    data-action=»woocommerce_json_search_products_and_variations» data-exclude=»<?php echo intval( $post->ID ); ?>»

    • Артем

      13.12.2017

      Все возможно. Что это за action? И что он делает?

      • Край

        13.12.2017

        «Произвольное поле. Выбор товаров с поиском»

        • Артем

          13.12.2017

          А при чем тут произвольное поле? Если это поиск и судя по всему аяксом предается, то в обработчике делайте еще запрос по таксономии да и все

  • Евгений

    10.01.2018

    Здравствуйте, как можно получить наше созданное поле в шаблоне?

    • Артем

      16.01.2018

      Доброго! В статье есть про это, целый раздел. Через get_post_meta

  • виктор

    11.01.2018

    Как можно настройить обновление цен товаров по атрибуту. В файле есть только атрибут и цена. нужно чтобы wp all import обновил цены по атрибуту. Можете направить на правильный путь ?

    • Артем

      16.01.2018

      wp all import вроде такое умеет и сам. Нет разве?

      • виктор

        16.01.2018

        Он обновляет только по артикулу и названию, так же по доп полям, в том числе и атрибуту — надо просто правильно все настроить.

  • Влад

    15.01.2018

    Возможно ли сделать чтобы в поле выбора товаров (Произвольное поле. Выбор товаров с поиском) выбранные товары не сортировались по имени?

    • Артем

      16.01.2018

      Скорее всего да, возможно, но надо ковырять код. Должен быть там фильтр

  • Денис

    17.01.2018

    Артём, приветствую.
    Отличная статья, пригодилось. А поиск по товарам с учётом этих новых полей возможен?

    • Артем

      20.01.2018

      Доброго! Возможен, только этот поиск придется вручную запиливать, поля-то кастомные

  • Артем

    19.01.2018

    Подскажите пожалуйста как отобразить все эти кастомные поля в превью товара? потому что отображаются они только на странице товара

    • Артем

      20.01.2018

      Подвешивать вывод на соответствующие хуки. Допишу статью

      • Артем

        20.01.2018

        благодарю! оповещение дожно прийти на почу когда допишите статью?)

        • Артем

          20.01.2018

          Хороший вопрос. Вроде нет у меня такой рассылки, на обновленные статьи… Значит буду делать простую рассылку по базе, повесил фору подписки в подвале. Подпишитесь, буду делать рассылки

  • Макс

    02.02.2018

    Спасибо за мануал, помог.
    Добавлял поле перед ценой что бы было Цена: от 1000, но в админке в меню «Все товары» в столбце «Цена» написано «отот1000». Как это подправить?

    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">';
    		woocommerce_wp_select( array(
    		   'id'      => '_select',
    		   'label'   => 'Значение перед ценой',
    		   'options' => array(
    		      ''   => __( 'нет', 'woocommerce' ),
    		      'от'   => __( 'от', 'woocommerce' ),
    		   ),
    		) );
    	echo '</div>';
    }
    
    add_action( 'woocommerce_process_product_meta', 'art_woo_custom_fields_save', 10 );
    function art_woo_custom_fields_save( $post_id ) {
       $woocommerce_select = $_POST['_select'];
       if ( $woocommerce_select ) {
          update_post_meta( $post_id, '_select', esc_attr( $woocommerce_select ) );
       }else {
          delete_post_meta( $post_id, '_select');
       }
      }
    
     add_action( 'woocommerce_get_price_suffix', 'art_get_select_before_add_card' );
    function art_get_select_before_add_card() {
    	global $post;
    	echo '<span class="price_suffix">';
    	echo get_post_meta( $post->ID, '_select', true );
    	echo '</span>';
    }
    
    • Артем

      02.02.2018

      С селектом что-то не так, зачем там передавать дважды? Ну и если дублируется вывод, значит где-то еще выводятся значения

  • Евгений

    05.02.2018

    Добрый день! Прошу помощи. Как вывести произвольные поля в админке в списке товаров?Под каждым товаром при наведении есть: Изменить,удалить,перейти дублировать и свойства. При нажатии на свойства, там не отображаются созданные поля.

    • Артем

      18.02.2018

      Добрый! Они и не будут отображаться. В эту панель Быстрого доступа отдельно добавлять надо через соответствующие хуки. Это тема отдельной статьи)

  • Джони Д

    25.03.2018

    Вроде профи, а шрифт просто нереально ужасный. Читать невозможно, глаза болят.

  • Руслан

    12.04.2018

    Здравствуйте!
    При использовании вашего кода для вывода во вкладке «Дополнительная информация» нужные поля отображаются только, когда отображается вкладка, т.е. в товаре присутствуют какие-либо атрибуты.
    Как сделать, чтобы вкладка отображалась, когда заполнено одно из дополнительных полей?

    • Артем

      12.04.2018

      Доброго! Не очень понял вопрос. Поля можно вывести на любой вкладке, в начале статьи все хуки написаны

      • Руслан

        13.04.2018

        Вопрос в том, как принудительно активировать вкладку, в данном случае «Дополнительная информация».

        • Артем

          28.04.2018

          Если правильно понял, то это проще скриптом классы подменять. Хотя надо доки посмотреть, точно не помню, но вроде было что-то при создании вкладок указывать ее активность

  • Вадим

    28.04.2018

    здравствуй Артём подскажи как сделать Вывод группы полей во вкладке которую я сделал, но не получается подставить значения то есть я не пойму как правильно заменить выражение

    add_action( 'woocommerce_product_additional_information', 'art_get_fields_tab_additional_information' );
    function art_get_fields_tab_additional_information() {
    
    если вкладка 
    
     // Добавление новой вкладки
     $tabs['test_tab'] = array(
     'title' => __( 'New Product Tab', 'woocommerce' ),
     'priority' => 50,
     'callback' => 'woo_new_product_tab_content',
     );
     return $tabs;
    }
    add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
    
    • Артем

      28.04.2018

      Все перепутано, ты пытаешься запихать и кладку и код какой-то
      Надо сначала вкладку добавить, а потом в нее уже выводить нужное, если я правильно понял задачу

      • Вадим

        29.04.2018

        Добрый вечер Артём подскажи как правильно уже голову сломал, плохо разбираюсь. заранее спасибо

      • Вадим

        29.04.2018

        Мне просто надо новую вкладку и чтоб в неё тест вставлять.

        • Артем

          29.04.2018

          Новую вкладку где? В админке или на странице товара?

          • Вадим

            29.04.2018

            на странице товара вкладку чтоб заполнялась из админки

          • Артем

            29.04.2018

            А при чем тут тогда дополнительные поля. Надо сначала вкладку добавить
            А потом только поля добавлять

          • Вадим

            29.04.2018

            В Вашей статье написано всё отлично, но мне надо чтоб не во вкладку additional_information, а в новую отображался текст

          • Вадим

            29.04.2018

            Я добавил вкладку

            add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
            function woo_new_product_tab( $tabs ) 
            { 
            // Добавление вкладки 
            $tabs['test_tab'] = array(
            'title' => __( 'Модули', 'woocommerce' ), // название ссылки для меню вкладки
            'priority' => 50,
            'callback' => 'woo_new_product_tab_content'
            ); 
            return $tabs; 
            }
            
          • Артем

            29.04.2018

            Ну теперь добавляйте поля и выводите данные в нужной вкладе. Это уже все есть в статье

  • Вадим

    29.04.2018

    Вот и не могу правильно написать ставлю вместо additional_information ставлю test_tab и ничего не получается

    • Артем

      29.04.2018

      woo_new_product_tab_content тут не причем, у вас же обозначен калбек woo_new_product_tab_content вот его и надо использовать. Вот из статьи по ссылке пример

      function woo_new_product_tab_content()  {
          // The new tab content
          $prod_id = get_the_ID();
          echo'<p>'.get_post_meta($prod_id,'additional information',true).'</p>';
      }
      

      Примерно так и выводить все

  • Вадим

    30.04.2018

    function woo_new_product_tab_content() {
    // The new tab content
    echo get_post_meta( $post->ID, ‘_text_field’, true );
    тоже не работает!

    • Артем

      30.04.2018

      Что значит не работает? Это же пример, может и не работать

  • Вадим

    30.04.2018

    Да в статье написано всё работает а пытаюсь отправить текст в новую вкладку ничего неполучаеться

  • Вадим

    30.04.2018

    Нашёл ошибку у себя лишний пробел

  • Вадим

    30.04.2018

    Доброе утро Артём, а как подставить wp_editor?

    • Артем

      30.04.2018

      Доброе! Зачем это подставлять?

  • Марианна

    26.05.2018

    Здравствуйте! Как сделать текстовое поле с редактором?

    • Артем

      31.05.2018

      Доброго! Такого поля нет по умолчанию. Придется или кастомное поле делать, или плагином воспользоваться

  • Кирилл

    28.05.2018

    Артем, добрый день, может подскажешь в какую сторону копать. Необходимо сделать возможность скачивания файла с инструкцией к товару. То есть: есть товар и есть инструкция к нему, соответственно ее нужно предоставить для скачивания.

    • Артем

      31.05.2018

      Добрый! Просто ссылку на пдф файл добавить например? Не подойдет?

  • Сергей

    14.06.2018

    Артём, здравствуйте. А знаете ли Вы что-нибудь по такому вопросу: как сделать проверку заполненности полей при добавлении товара в WooCommerce? Дело в том, что контент-менеджеры, которые наполняют магазин, забывают вписать то артикул, то краткое описание, то ещё что-нибудь… Подскажите, пожалуйста, если есть знания по этому вопросу.

    • Артем

      17.06.2018

      Доброго! Можно в поля добавлять произвольные атрибуты required для обязательности. Примерно так

      woocommerce_wp_text_input( array(
      		'id'                => '_text_field',
      		'label'             => __( 'Текстовое поле', 'woocommerce' ),
      		'placeholder'       => 'Текстовое поле',
      		'desc_tip'          => 'true',
      		'custom_attributes' => array( 'required' => 'required' ),
      		'description'       => __( 'Введите здесь значение поля', 'woocommerce' ),
      	) );
      

      Хотя как добавить к существующим полям обязательность — не знаю, как-то не приходилось такого делать

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *
php js HTML CSS Code