Как выводить в цикле wordpress несколько постов без дублирования?
Когда пытаюсь вывести в цикле посты с несколькими тегами посты дублируются. При этом если вывродим внтури категории пост с 1 тегом, то все норм. Где я не прав? Пробовал циклы менять местами, закрывать циклы чтобы было 2 endforeach на каждый цикл, тогда вообще не работает. Надо чтобы, если у поста внтури категории больше одного тега выводился только один пост.Сейчас если 2 тега у поста выводятся 2 одинаковых поста. Прим. На странице 5 табов. Внтури табов +/- одинаковый код только разница с тем из какой категории выводятся посты.
<div id="tab-3" class="tab__content hidden-tab-content"> //Получаем посты из категории 4 по 4 поста <?php $posts = get_posts ("category=4&orderby=date&numberposts=4"); ?> <?php if ($posts) : ?> <?php foreach ($posts as $post) : setup_postdata ($post); ?> //Получаем теги для поста <?php $tags = wp_get_post_tags($post->ID); foreach ($tags as $tag) { $tag_link = get_tag_link($tag->term_id);?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> //Выводим ссылки на теги <a href="<?php echo $tag_link; ?>"> //и картинку поста <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" ></a> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></p> <p class="product-short"><?php the_field('short_diskr_post') ?></p> </div> </div> </div> <?php } ?> <?php wp_reset_postdata(); ?> <?php endforeach; ?> <?php endif; ?> </div> |
<div id="tab-3" class="tab__content hidden-tab-content"> //Получаем посты из категории 4 по 4 поста <?php $posts = get_posts ("category=4&orderby=date&numberposts=4"); ?> <?php if ($posts) : ?> <?php foreach ($posts as $post) : setup_postdata ($post); ?> //Получаем теги для поста <?php $tags = wp_get_post_tags($post->ID); foreach ($tags as $tag) { $tag_link = get_tag_link($tag->term_id);?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> //Выводим ссылки на теги <a href="<?php echo $tag_link; ?>"> //и картинку поста <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" ></a> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></p> <p class="product-short"><?php the_field('short_diskr_post') ?></p> </div> </div> </div> <?php } ?> <?php wp_reset_postdata(); ?> <?php endforeach; ?> <?php endif; ?> </div>
Если к посту поставить 2 тега то выведется один и тот же пост в этой категории с двумя тегами. Т.е. дубль. Почему, как этого избежать, где я ошибся?
Дополнительно:
Ответы:
Добавить global $post; в начало, если его там нет.
Перенести wp_reset_postdata(); за endforeach;
Если сработает, то почитать почему.
Не помогло. Выносил wp_reset_postdata(); и global $post; добавлял. Возможно доавлял не туда но я перетыкал везде где молжно и не можно. Или вы хотели чтобы я к каждому циклу их 5 добавил?
<?php $args = array( 'category' => 4, 'orderby' => 'date', 'posts_per_page' => 4, ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); ?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> <?php $tags = get_the_tags(); ?> <?php if ( $tags ) { ?> <ul class="tag-list"> <?php foreach ( $tags as $key => $tag ) { ?> <li class="tag-list__item"> <a href="<?php echo get_tag_link( $tag->term_id ); ?>" class="product-tag"></a> </li> <?php } ?> </ul> <?php } ?> <img src="<?php the_post_thumbnail_url( 'medium' ); ?>" class="product-img img-responsive" ></a> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></p> <?php if ( get_field( 'short_diskr_post' ) ): ?> <p class="product-short"><?php the_field( 'short_diskr_post' ); ?></p> <?php endif; ?> </div> </div> </div> <?php } } wp_reset_postdata(); ?> |
<?php $args = array( 'category' => 4, 'orderby' => 'date', 'posts_per_page' => 4, ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); ?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> <?php $tags = get_the_tags(); ?> <?php if ( $tags ) { ?> <ul class="tag-list"> <?php foreach ( $tags as $key => $tag ) { ?> <li class="tag-list__item"> <a href="<?php echo get_tag_link( $tag->term_id ); ?>" class="product-tag"></a> </li> <?php } ?> </ul> <?php } ?> <img src="<?php the_post_thumbnail_url( 'medium' ); ?>" class="product-img img-responsive" ></a> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></p> <?php if ( get_field( 'short_diskr_post' ) ): ?> <p class="product-short"><?php the_field( 'short_diskr_post' ); ?></p> <?php endif; ?> </div> </div> </div> <?php } } wp_reset_postdata(); ?>
-
<?php $posts = get_posts("category=4&orderby=date&numberposts=4"); if ($posts) : foreach ($posts as $post) : setup_postdata ($post); $tags = wp_get_post_tags($post->ID); // Получаем первый тег для поста $tag = $tags[0] ?? false; ?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> <?php if ($tag) : ?> <a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>"> <?php endif; ?> <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" > <?php if ($tag) : ?> </a> <?php endif; ?> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></p> <p class="product-short"><?php the_field('short_diskr_post') ?></p> </div> </div> </div> <?php endforeach; wp_reset_postdata(); ?> <?php endif; ?>
<?php $posts = get_posts("category=4&orderby=date&numberposts=4"); if ($posts) : foreach ($posts as $post) : setup_postdata ($post); $tags = wp_get_post_tags($post->ID); // Получаем первый тег для поста $tag = $tags[0] ?? false; ?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> <?php if ($tag) : ?> <a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>"> <?php endif; ?> <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" > <?php if ($tag) : ?> </a> <?php endif; ?> <div class="product-discr"> <p class="product-h"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></p> <p class="product-short"><?php the_field('short_diskr_post') ?></p> </div> </div> </div> <?php endforeach; wp_reset_postdata(); ?> <?php endif; ?>
Спасибо за ответ вся задуманная логика была в том чтобы миниатюра была ссылкой на страницу тегов. Так чтобы пользователь щёлкая на картинку попадал на старницу с тегами записей, а на странице выводился бы текст о теге.
В коде выше этого нет(. Но решение предложили.
Тут был вопрос, как поступить если тегов больше одного т.к. место для заголовко одно. То что предложили на другом форуме// Получаем первый тег для поста $tag = $tags[0] ?? false;// Получаем первый тег для поста $tag = $tags[0] ?? false;
но это не очень гибко т.к. сложно объяснить как в итоге выборать первый тег из трёх четрыёх/пяти/шести, т.е. какой тег берется первым. и на какую старницу в итоге перенаправят пользователя. Однако способ с первым тегом решает проблему что выводить в заголовок т.к. в заголовок на странице тегов подставляется этот же первый тег.
Есть ли какое-то более удобное решение? Если кто-то знает, подклитесь кодом пожалуйста. Спасибо за ответ выше. прикладываю этот код чтобы у людей были варианты.
- solomonfox, прочитал несколько раз, но так и не понял задачу. Вы получаете массив тегов $tags. Вы знаете их количество и по числовому индексу можете выбрать нужный, $tags[0] это первый элемент массива
if ( count( $tags ) > 0 ) { echo $tags[0]; }
if ( count( $tags ) > 0 ) { echo $tags[0]; }
- Артем Золин, Как сейчас. При клике на изображение поста за счёт кода
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>"> <?php endif; ?> <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" > <?php if ($tag) : ?> </a>
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>"> <?php endif; ?> <img src="<?php the_post_thumbnail_url('medium'); ?>" class="product-img img-responsive" > <?php if ($tag) : ?> </a>
мы переходим на страницу с тегами данного поста. Заголовок на странице меняется согласно тегу, который присвоен посту. Если тегов у поста несколько берется первый тег вот тут
$tag = $tags[0] ?? false; ?>
$tag = $tags[0] ?? false; ?>
Тут все работает, но решение не очень гибкое т.к. сложно объяснить откуда берется первый тег. Как мы можем менять на какую страницу перенаправит пользователя. Т.е. условно есть статья про шины и к ней 2 тега "Лада" и "Жигули." "Лада" 0 тег "Жигули" нет. таким образом пользователя всегда будет перенаправлять на старницу с тегами про Лада, а про Жигули мы как бы забудет. можно как, то сделать решение более гибким. Моно например, чтобы админ через админку может менять первый тег и стоответвенно менялась бы страница кудв его перешлют после клика?
- solomonfox, в ядре такого функционала нет. С точки зрения здравого смысла лучше показывать пользователю все теги поста и пусть он сам выбирает куда ему переходить
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

Дубли появляются потому, что карточка поста выводится внутри цикла по тегам. Если у записи два тега, внутренний
foreach ($tags as $tag)два раза печатает всю карточку. Цикл по тегам должен выводить только список тегов или нужно брать один тег для ссылки.Если картинка должна вести на первый тег записи, вынесите карточку из цикла по тегам:
$posts = get_posts([ 'cat' => 4, 'orderby' => 'date', 'posts_per_page' => 4, ]); foreach ($posts as $post) { setup_postdata($post); $tags = wp_get_post_tags(get_the_ID()); $tag = $tags[0] ?? null; $url = $tag ? get_tag_link($tag->term_id) : get_permalink(); ?> <div class="col-md-3 col-sm-3 col-xs-12 off-pd line-item"> <div class="prod-card"> <a href="<?php echo esc_url($url); ?>"> <img src="<?php echo esc_url(get_the_post_thumbnail_url(get_the_ID(), 'medium')); ?>" class="product-img img-responsive" alt=""> </a> <p class="product-h"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></p> </div> </div> <?php } wp_reset_postdata();
Если нужно показать все теги, делайте отдельный список тегов внутри карточки, но саму карточку не повторяйте. И
wp_reset_postdata()ставьте после завершения внешнего цикла, а не внутри каждой итерации.Дубли появляются потому, что вы, скорее всего, перебираете теги внутри каждого поста и выводите сам пост в цикле по тегам. Если у записи два тега, она выводится два раза. Пост нужно выводить один раз, а теги — уже внутри карточки как список меток.
Правильная схема такая: сначала получаем посты категории, потом внутри карточки получаем термины записи и выводим их, но не запускаем отдельный внешний цикл по тегам.
$posts = get_posts([ 'category' => 4, 'numberposts' => 4, 'orderby' => 'date', 'order' => 'DESC', ]); foreach ($posts as $post) { setup_postdata($post); echo '<article class="post-card">'; echo '<h3>' . esc_html(get_the_title()) . '</h3>'; $tags = get_the_tags(); if ($tags) { echo '<div class="post-tags">'; foreach ($tags as $tag) { echo '<span>' . esc_html($tag->name) . '</span>'; } echo '</div>'; } echo '</article>'; } wp_reset_postdata();
Если вам нужно отобрать посты сразу по нескольким тегам, используйте
tag__inилиtax_query, а не ручной перебор тегов с выводом записи. WordPress сам вернёт каждую запись один раз:$query = new WP_Query([ 'cat' => 4, 'tag__in' => [10, 12], 'posts_per_page' => 4, ]);
Если дубли всё равно появляются из-за сложного SQL, добавьте
'fields' => 'ids'и прогоните ID черезarray_unique(), но в обычном случае это не требуется.