Как найти в категории все значения field и вывести в блоке якорями?

Ссылка скопирована
PHP
1 ответ

Делаю сайт WP + Woocommerce. Задача такая: вывести в категории отдельно параметр всех товаров - Диаметр.
Пытаюсь вывести вот так:

<?php         global $woocommerce ,$product, $post;          $num_field      = get_post_meta( $post->ID, 'diametr_number_field', true );         if ( $num_field ) { ?> <a href="#<?php echo $num_field ?>" rel="bookmark">         <?php echo $num_field ?>     </a> <?php          }           ?>

<?php global $woocommerce ,$product, $post; $num_field = get_post_meta( $post->ID, 'diametr_number_field', true ); if ( $num_field ) { ?> <a href="#<?php echo $num_field ?>" rel="bookmark"> <?php echo $num_field ?> </a> <?php } ?>

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

Дополнительно

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Никита Орлов Ответ

У вас выводится диаметр только первого товара, потому что код берет значение из текущего глобального объекта записи, а не из всех товаров категории. На архиве WooCommerce переменная текущего поста меняется внутри основного цикла, но сама по себе она не дает список всех товаров. Для такой задачи нужно отдельно получить товары текущей товарной категории, пройти по их ID, прочитать meta-поле diametr_number_field, убрать пустые значения и дубли, а затем вывести ссылки-якоря.

Минимальный рабочий вариант для архива категории товаров выглядит так. Код лучше размещать в шаблоне категории WooCommerce или в функции, которую вызываете в нужном месте шаблона, а не прямо в случайном фрагменте внутри карточки товара.

$term = get_queried_object();
$diameters = [];
 
if ($term instanceof WP_Term && $term->taxonomy === 'product_cat') {
    $products = new WP_Query([
        'post_type' => 'product',
        'post_status' => 'publish',
        'posts_per_page' => -1,
        'fields' => 'ids',
        'tax_query' => [[
            'taxonomy' => 'product_cat',
            'field' => 'term_id',
            'terms' => [(int) $term->term_id],
        ]],
    ]);
 
    foreach ($products->posts as $product_id) {
        $diameter = trim((string) get_post_meta($product_id, 'diametr_number_field', true));
 
        if ($diameter !== '') {
            $diameters[$diameter] = $diameter;
        }
    }
 
    wp_reset_postdata();
}
 
$diameters = array_values($diameters);
natsort($diameters);
 
if ($diameters) {
    echo '<div class="diameter-links">';
 
    foreach ($diameters as $diameter) {
        $anchor_id = 'diametr-' . sanitize_title($diameter);
        echo '<a href="#' . esc_attr($anchor_id) . '">' . esc_html($diameter) . '</a>';
    }
 
    echo '</div>';
}

$term = get_queried_object(); $diameters = []; if ($term instanceof WP_Term && $term->taxonomy === 'product_cat') { $products = new WP_Query([ 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'fields' => 'ids', 'tax_query' => [[ 'taxonomy' => 'product_cat', 'field' => 'term_id', 'terms' => [(int) $term->term_id], ]], ]); foreach ($products->posts as $product_id) { $diameter = trim((string) get_post_meta($product_id, 'diametr_number_field', true)); if ($diameter !== '') { $diameters[$diameter] = $diameter; } } wp_reset_postdata(); } $diameters = array_values($diameters); natsort($diameters); if ($diameters) { echo '<div class="diameter-links">'; foreach ($diameters as $diameter) { $anchor_id = 'diametr-' . sanitize_title($diameter); echo '<a href="#' . esc_attr($anchor_id) . '">' . esc_html($diameter) . '</a>'; } echo '</div>'; }

Такой код делает три важные вещи: работает именно с товарами, а не с обычными записями; ограничивает выборку текущей product_cat категорией; выводит каждое значение только один раз. Если у нескольких товаров одинаковый диаметр, ссылка для этого диаметра все равно будет одна, потому что массив использует значение диаметра как ключ.

  • Если якорь должен вести к секции с товарами конкретного диаметра, на этой секции должен быть такой же id, например diametr-120.
  • Если якорь должен вести к конкретному товару, нельзя использовать один и тот же id для нескольких товаров с одинаковым диаметром. Тогда нужно строить ссылки на товары или группировать товары по диаметру.
  • Если диаметр является атрибутом WooCommerce, а не произвольным meta-полем, лучше читать атрибут товара или сделать диаметр таксономией. Для фильтров, архивов и SEO это обычно надежнее, чем хранить важный параметр в post meta.

Для маленьких категорий запрос с posts_per_page -1 допустим. Если товаров сотни или тысячи, такой список лучше кэшировать по ID категории через transient и сбрасывать кэш при сохранении товара. Иначе каждый просмотр категории будет заново обходить все товары и читать meta, что может заметно замедлить архив.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно