
Продолжение статьи про создание дополнительных полей для товаров через API WooCommerce, но теперь для вариативных товаров. И разбирать будем на конкретном примере.
functions.php
или например пустой плагин. Прежде чем, вносить какие либо изменения, сделайте бекап сайта.В качестве примера, создадим отдельное поле для добавления срока изготовления товаров. Это будет простое нумерованное поле.
Про создание произвольных полей и их всевозможных вариантах читайте в отдельной статье
к содержаниюШаг первый. Создание поля
Поля для вариативных товаров создаются точно так же, как и для простых используя соответствующую функцию. В нашем варианте — woocommerce_wp_text_input()
. Ну и для вывода в нужном месте будем подвешивать на хук woocommerce_product_after_variable_attributes
. Получиться такое решение
add_action( 'woocommerce_product_after_variable_attributes', 'art_term_production_fields', 10, 3 );
function art_term_production_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => '_term_prod_var[' . $variation->ID . ']', // id поля
'label' => 'Срок изготовления', // Надпись над полем
'description' => 'Укажи срок изготовления, просто цифры в днях',// Описание поля
'desc_tip' => 'true', // Всплывающая подсказка
'placeholder' => 'Срок изготовления, дн', // Надпись внутри поля
'type' => 'number', // Тип поля
'custom_attributes' => array( // Произвольные аттрибуты
'step' => 'any', // Шаг значений
'min' => '0', // Минимальное значение
),
'value' => get_post_meta( $variation->ID, '_term_prod_var', true ),
) );
}
Получаем вот такое поле, в каждой вариации товара

Можно вывести поле и в другом месте, где-то выше, например. Для этого используйте соответствующие хуки

woocommerce_variation_options
— после чекбоксовwoocommerce_variation_options_pricing
— после ценыwoocommerce_variation_options_inventory
— после статуса остатковwoocommerce_variation_options_dimensions
— после размеровwoocommerce_variation_options_tax
— после класса доставки
Поле есть, но оно пока ничего не сохраняет. Давайте исправим это.
к содержаниюШаг второй. Сохранение значений
Что бы поле сохраняло введенные значения, требуется использовать хук woocommerce_save_product_variation
. Примерно так
add_action( 'woocommerce_save_product_variation', 'art_save_variation_settings_fields', 10, 2 );
function art_save_variation_settings_fields( $post_id ) {
$woocommerce__term_prod_var = $_POST['_term_prod_var'][ $post_id ];
if (isset($woocommerce__term_prod_var) && ! empty( $woocommerce__term_prod_var ) ) {
update_post_meta( $post_id, '_term_prod_var', esc_attr( $woocommerce__term_prod_var ) );
}
}
Алгоритм простой:
- ловим значение в глобальной переменной
$_POST
; - проверяем нужное значение на существование;
- если все нормально, тогда записываем/перезаписываем значение в поле.
Вот теперь все работает как надо. Поле есть и значения в нем сохраняются. Теперь надо эти значения вывести на странице товара.
к содержаниюШаг третий. Вывод значений
В вариативных товарах это не совсем простая задача. Для начала, необходимо через хук woocommerce_available_variation
добавить значения нашего поля в общий массив вывода данных вариаций. Вот таким образом
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
function load_variation_settings_fields( $variations ) {
$variations_time = get_post_meta( $variations['variation_id'], '_term_prod_var', true );
if ( isset( $variations_time ) && ! empty( $variations_time ) ) {
$variations['_term_prod_var'] = '<div class="term-production">';
$variations['_term_prod_var'] .= '<span>Срок изготовления </span>';
$variations['_term_prod_var'] .= get_post_meta( $variations['variation_id'], '_term_prod_var', true ) . ' дн.';
$variations['_term_prod_var'] .= '</div>';
}
return $variations;
}
Алгоритм тот же, что и выше:
- получаем значение поля;
- проверяем значение на существование;
- если все нормально, тогда добавляем значение в массив.
Теперь надо вывести на странице товара. Нужных хуков не нашел, а потому придется воспользоваться заменой файлов. Для этого надо сделать так:
- создать в коневой папке темы папку
woocommerce
; - в папку
woocommerce
скопировать из папкиtemplates
самого плагина папкуsingle-product
и все что в ней находиться; - открыть файл
variation.php
, который будет находиться по адресуваша_тема/woocommerce/single-product/add-to-cart
;
Осталось добавить в файл значение нашего поля
<div class="woocommerce-variation-custom-text-field ">
{{{ data.variation._term_prod_var }}}
</div>
Примерно так, можно выше или ниже, главное внутри тега <script>
размещать код

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

На этом можно было бы и закончить, но возникает проблема: добавлять значения в поле если больше 2-3-х вариаций вручную еще можно, а что делать если этих вариаций десяток или два?
к содержаниюШаг четвертый. Массовое изменение поля
Для этого есть в WooCommerce специальное решение по массовому заполнению полей всех вариаций сразу. Например, можно указать базовую цену сразу для всех вариаций

Такую же фичу можно сделать и для нашего поля. Сначала добавим в выпадающий список нужное значение
add_action( 'woocommerce_variable_product_bulk_edit_actions', 'art_actions_variation_settings_fields', 10, 1 );
function art_actions_variation_settings_fields() {
?>
<option data-global="true" value="variation_prod_time">Срок изготовления</option>
<?php
}
Получиться вот так

Теперь надо заставить работать данный пункт. Без ajax не обойтись. Добавляем код, который будет подрубать наш скрипт с аяксом сразу в подвал админки
add_action( 'admin_footer', 'art_script_add_all_variation_select' );
function art_script_add_all_variation_select() {
?>
<script>
jQuery(function ($) {
jQuery('.wc-metaboxes-wrapper').on('click', 'a.bulk_edit', function (event) {
var do_variation_term = jQuery('select.variation_actions').val();
var data = {},
value;
if ('variation_prod_time' === do_variation_term) {
value = window.prompt(woocommerce_admin_meta_boxes_variations.i18n_enter_a_value);
if (null !== value) {
data.value = value;
} else {
return;
}
jQuery.ajax({
url: woocommerce_admin_meta_boxes_variations.ajax_url,
data: {
action: 'woocommerce_bulk_edit_variations',
security: woocommerce_admin_meta_boxes_variations.bulk_edit_variations_nonce,
product_id: woocommerce_admin_meta_boxes_variations.post_id,
product_type: jQuery('#product-type').val(),
bulk_action: do_variation_term,
data: data
},
type: 'POST',
success: function (data) {
jQuery('.variations-pagenav .page-selector').val(1).first().change();
//console.log(data.product_id);
}
});
jQuery('#woocommerce-product-data').unblock();
}
});
});
</script>
<?php
}
Вот теперь работает, но пока не сохраняет значения. Для сохранения добавим обновление полей, если сработал скрипт
add_action( 'woocommerce_bulk_edit_variations_default', 'action_woocommerce_bulk_edit_variations_default', 10, 4 );
function action_woocommerce_bulk_edit_variations_default( $bulk_action, $data, $product_id, $variations ) {
if ( 'variation_prod_time' === $bulk_action ) {
foreach ( $variations as $variation ) {
update_post_meta( $variation, '_term_prod_var', $data['value'] );
}
}
exit;
}
Вот и все. Профит! Весь код рабочий и проверен на реальных проектах.
к содержаниюПолностью весь код
Кроме изменений в файлах
/**
* Создаем текстовое поле
*
* @param $loop
* @param $variation_data
* @param $variation
*/
add_action( 'woocommerce_product_after_variable_attributes', 'art_term_production_fields', 10, 3 );
function art_term_production_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => '_term_prod_var[' . $variation->ID . ']', // id поля
'label' => 'Срок изготовления', // Надпись над полем
'description' => 'Укажи срок изготовления, просто цифры в днях',// Описание поля
'desc_tip' => 'true', // Всплывающая подсказка
'placeholder' => 'Срок изготовления, дн', // Надпись внутри поля
'type' => 'number', // Тип поля
'custom_attributes' => array( // Произвольные аттрибуты
'step' => 'any', // Шаг значений
'min' => '0', // Минимальное значение
),
'value' => get_post_meta( $variation->ID, '_term_prod_var', true ),
) );
}
/**
* Сохраняем значение поля
*
* @param $post_id
*/
add_action( 'woocommerce_save_product_variation', 'art_save_variation_settings_fields', 10, 2 );
function art_save_variation_settings_fields( $post_id ) {
$woocommerce__term_prod_var = $_POST['_term_prod_var'][ $post_id ];
if ( isset( $woocommerce__term_prod_var ) && ! empty( $woocommerce__term_prod_var ) ) {
update_post_meta( $post_id, '_term_prod_var', esc_attr( $woocommerce__term_prod_var ) );
}
}
/**
* Добавляем значение поле в массив данных
*
* @param $variations
*
* @return mixed
*/
add_filter( 'woocommerce_available_variation', 'art_load_variation_settings_fields' );
function art_load_variation_settings_fields( $variations ) {
$variations_time = get_post_meta( $variations['variation_id'], '_term_prod_var', true );
if ( isset( $variations_time ) && ! empty( $variations_time ) ) {
$variations['_term_prod_var'] = '<div class="term-production">';
$variations['_term_prod_var'] .= '<span>Срок изготовления </span>';
$variations['_term_prod_var'] .= get_post_meta( $variations['variation_id'], '_term_prod_var', true ) . ' дн.';
$variations['_term_prod_var'] .= '</div>';
}
return $variations;
}
/**
* Добавляем пункт выпадающего списка в админке
*/
add_action( 'woocommerce_variable_product_bulk_edit_actions', 'art_actions_variation_settings_fields', 10, 1 );
function art_actions_variation_settings_fields() {
?>
<option data-global="true" value="variation_prod_time">Срок изготовления</option>
<?php
}
/**
* Добавляем аякс для массового изменения поля
*/
add_action( 'admin_footer', 'art_script_add_all_variation_select' );
function art_script_add_all_variation_select() {
?>
<script>
jQuery(function ($) {
jQuery('.wc-metaboxes-wrapper').on('click', 'a.bulk_edit', function (event) {
var do_variation_term = jQuery('select.variation_actions').val();
var data = {},
value;
if ('variation_prod_time' === do_variation_term) {
value = window.prompt(woocommerce_admin_meta_boxes_variations.i18n_enter_a_value);
if (null !== value) {
data.value = value;
} else {
return;
}
jQuery.ajax({
url: woocommerce_admin_meta_boxes_variations.ajax_url,
data: {
action: 'woocommerce_bulk_edit_variations',
security: woocommerce_admin_meta_boxes_variations.bulk_edit_variations_nonce,
product_id: woocommerce_admin_meta_boxes_variations.post_id,
product_type: jQuery('#product-type').val(),
bulk_action: do_variation_term,
data: data
},
type: 'POST',
success: function (data) {
jQuery('.variations-pagenav .page-selector').val(1).first().change();
//console.log(data.product_id);
}
});
jQuery('#woocommerce-product-data').unblock();
}
});
});
</script>
<?php
}
/**
* Сохранение значения для массового изменения
*
* @param $bulk_action
* @param $data
* @param $product_id
* @param $variations
*/
add_action( 'woocommerce_bulk_edit_variations_default', 'action_woocommerce_bulk_edit_variations_default', 10, 4 );
function action_woocommerce_bulk_edit_variations_default( $bulk_action, $data, $product_id, $variations ) {
if ( 'variation_prod_time' === $bulk_action ) {
foreach ( $variations as $variation ) {
update_post_meta( $variation, '_term_prod_var', $data['value'] );
}
}
exit;
}
Вопросы задаем в комментариях. Всем пока-пока…