WooCommerce add extra field to variation product
Я следую этому руководству о том, как добавить дополнительное поле к моим вариативным товарам.
Мне просто нужно добавить дополнительное текстовое поле. Административная часть работает нормально - поле отображается и сохраняется/обновляется, однако на странице отдельного товара поле не отображается.
Итак, в мой functions.php
я добавил:
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input(
array(
'id' => '_text_field[' . $variation->ID . ']',
'label' => __( 'Некоторая метка', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'Некоторое описание.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_text_field', true )
)
);
}
function save_variation_settings_fields( $post_id ) {
$text_field = $_POST['_text_field'][ $post_id ];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, '_text_field', esc_attr( $text_field );
}
}
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
function load_variation_settings_fields( $variations ) {
$variations['text_field'] = get_post_meta( $variations[ 'variation_id' ], '_text_field', true );
return $variations;
}
И в plugins/plugins/woocommerce/templates/single-product/add-to-cart/variation.php
я добавил (в теме нет собственного variation.php
):
<div class="woocommerce-variation-custom-text-field">
{{{ data.variation.text_field }}}
</div>
Как отобразить пользовательское поле на странице товара?
Спасибо
Обновление: Если я проверяю страницу товара, скрипт присутствует:
<script type="text/template" id="tmpl-variation-template">
<div class="woocommerce-variation-description">
{{{ data.variation.variation_description }}}
</div>
<div class="woocommerce-variation-price">
{{{ data.variation.price_html }}}
</div>
<div class="woocommerce-variation-custom-text-field">
{{{ data.variation.text_field }}}
</div>
<div class="woocommerce-variation-availability">
{{{ data.variation.availability_html }}}
</div>
</script>
Тема - belise.
Обновление: Я просматриваю пользовательский файл functions.php
WooCommerce темы (belise/inc/woocommerce/functions.php) и похоже, что логика там есть.
/**
* Описание на странице магазина woocommerce-Price-amount amount для архивов продуктов
*/
function belise_woocommerce_template_single_excerpt() {
global $post;
if ( ! $post->post_excerpt ) {
return;
}
?>
<div class="woocommerce-Price-amount amountption" itemprop="woocommerce-Price-amount amountption">
<!-- если я добавлю <p>test</p>, он отображается на странице товара -->
<!-- я хотел бы, чтобы элемент пользовательского поля отображался здесь -->
<?php echo apply_filters( 'woocommerce_short_woocommerce-Price-amount amountption', $post->post_excerpt ); ?>
</div><?php
}
Ответ - первое решение @ClemC работает, поле не отображалось из-за кэша браузера.

Для серьезного примера смотрите, как сам WC добавляет текстовое поле variable_description
к вариациям здесь.
Мы заметили несколько (потенциальных) проблем в вашей реализации текстового поля.
- Отсутствует атрибут
name
... - Строка
id
имеет неправильную структуру, она соответствует структуреname
... - Атрибуты
id
илиname
не совпадают с теми, что используются в вашем шаблоне...
Итак, беря за основу реализацию текстового поля variable_description
в WC, давайте реализуем наше текстовое поле следующим образом:
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input(
array(
'id' => "my_text_field{$loop}",
'name' => "my_text_field[{$loop}]",
'value' => get_post_meta( $variation->ID, 'my_text_field', true ),
'label' => __( 'Название поля', 'woocommerce' ),
'desc_tip' => true,
'description' => __( 'Описание поля.', 'woocommerce' ),
'wrapper_class' => 'form-row form-row-full',
)
);
}
function save_variation_settings_fields( $variation_id, $loop ) {
$text_field = $_POST['my_text_field'][ $loop ];
if ( ! empty( $text_field ) ) {
update_post_meta( $variation_id, 'my_text_field', esc_attr( $text_field ));
}
}
function load_variation_settings_fields( $variation ) {
$variation['my_text_field'] = get_post_meta( $variation[ 'variation_id' ], 'my_text_field', true );
return $variation;
}
Теперь в шаблоне, который обязан находиться по следующему пути:
yourtheme/woocommerce/single-product/add-to-cart/variation.php
Добавьте это:
<div class="random-class woocommerce-variation-custom-text-field">
{{{ data.variation.my_text_field }}}
</div>
ИЗМЕНЕНИЕ:
Если вы хотите вывести ваше пользовательское поле "классическим" способом:
<div class="woocommerce-variation-custom-text-field">
<p><?php echo esc_html( get_post_meta( $post->ID, 'my_text_field', true ) ); ?></p>
</div>

Комментарии не предназначены для длительных обсуждений; этот разговор был перенесен в чат.

var_dump(get_post_meta( $post->ID, 'my_text_field', true ))
возвращает string(0) ""
, даже если в моем пользовательском поле сохранена строка.

Я думаю, это из-за $post->ID
, который не является вариацией и для которого вы не вводили значение 'my_text_field'
. Вам действительно нужно находиться внутри цикла вариаций. Судя по тому, откуда вы пытаетесь вывести метаполе, получается, что ОДИНАКОВОЕ метаполе будет присутствовать для всех вариаций и самого основного товара - это не то, что вам нужно. Текстовое поле должно отображаться только для своей вариации.

У вас действительно не так много других вариантов, кроме как сделать это с помощью нашего первого подхода. Я бы предложил вам перейти в чат для решения вашей проблемы.

Давайте продолжим это обсуждение в чате.

Это отлично, спасибо @ClemC - есть одна небольшая проблема: я могу редактировать текст в поле и сохранять его снова, однако если я удалю все содержимое и затем сохраню, изменения, кажется, не сохраняются?

Ах, просто удалите if ( ! empty( $field ) ) {}, и всё заработает. Есть ли какие-то недостатки в таком решении?
