Как отобразить похожие записи из той же категории?
Один из вариантов:
$related = get_posts(
array(
'category__in' => wp_get_post_categories( $post->ID ),
'numberposts' => 5,
'post__not_in' => array( $post->ID )
)
);
if( $related ) {
foreach( $related as $post ) {
setup_postdata($post);
/*здесь может быть любой вывод поста*/
}
wp_reset_postdata();
}
Ссылки на документацию:
Переписанный вариант с использованием WP_Query()
:
$related = new WP_Query(
array(
'category__in' => wp_get_post_categories( $post->ID ),
'posts_per_page' => 5,
'post__not_in' => array( $post->ID )
)
);
if( $related->have_posts() ) {
while( $related->have_posts() ) {
$related->the_post();
/*здесь может быть любой вывод поста*/
}
wp_reset_postdata();
}

Будьте очень осторожны с именами переменных! Вы используете глобальную переменную $post
для выполнения запроса, затем переопределяете $post
в том же контексте внутри вашего цикла foreach
.

@EAMann - в целом вы правы, но по моему опыту использование setup_postdata()
с чем-либо кроме $post
не дает правильного вывода для функций типа the_title()
. Теоретически wp_reset_postdata()
должна сбрасывать $post обратно.

Это потому что сама функция setup_postdata()
ссылается на глобальную переменную $post
. Вместо использования get_posts()
вам следует создать кастомный экземпляр WP_Query
и использовать его для получения записей. Это автоматически настроит данные записи и заставит the_title()
и другие функции работать как положено.

Еще один чистый и очень гибкий вариант:
Поместите этот код в файл functions.php
function example_cats_related_post() {
$post_id = get_the_ID();
$cat_ids = array();
$categories = get_the_category( $post_id );
if(!empty($categories) && is_wp_error($categories)):
foreach ($categories as $category):
array_push($cat_ids, $category->term_id);
endforeach;
endif;
$current_post_type = get_post_type($post_id);
$query_args = array(
'category__in' => $cat_ids,
'post_type' => $current_post_type,
'post__not_in' => array($post_id),
'posts_per_page' => '3'
);
$related_cats_post = new WP_Query( $query_args );
if($related_cats_post->have_posts()):
while($related_cats_post->have_posts()): $related_cats_post->the_post(); ?>
<ul>
<li>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
<?php the_content(); ?>
</li>
</ul>
<?php endwhile;
// Восстановление оригинальных данных поста
wp_reset_postdata();
endif;
}
Теперь вы можете просто вызвать функцию в любом месте вашего сайта, используя:
<?php example_cats_related_post() ?>
Вы можете удалить элементы списка или стилизовать их по своему усмотрению.
*Примечание - вам нужно изменить: post_not_in на post__not_in в вашем запросе

Вы можете использовать этот код для получения связанных записей из той же категории
$args = array(
'category__in' => wp_get_post_categories( get_queried_object_id() ),
'posts_per_page' => 5,
'orderby' => 'rand',
'post__not_in' => array( get_queried_object_id() )
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) : ?>
<ul class="">
<!-- цикл -->
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<li>
<h6>
<a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
<?php the_title(); ?>
</a>
</h6>
</li>
<?php endwhile; ?>
<!-- конец цикла -->
</ul>
<?php wp_reset_postdata(); ?>
<?php endif; ?>
и используйте этот код для получения связанных записей с теми же метками
$tags = wp_get_post_terms( get_queried_object_id(), 'post_tag', ['fields' => 'ids'] );
$args = [
'post__not_in' => array( get_queried_object_id() ),
'posts_per_page' => 5,
'orderby' => 'rand',
'tax_query' => [
[
'taxonomy' => 'post_tag',
'terms' => $tags
]
]
];
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) : ?>
<ul class="">
<!-- цикл -->
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<li>
<h6>
<a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
<?php the_title(); ?>
</a>
</h6>
</li>
<?php endwhile; ?>
<!-- конец цикла -->
</ul>
<?php wp_reset_postdata(); ?>
<?php endif; ?>

Этот ответ гарантирует, что связанные записи сортируются по количеству совпадающих тегов.
Например, если у записи есть 3 тега и существует другая запись с точно такими же 3 тегами, она должна отображаться вверху списка. Вторичная сортировка должна быть по дате публикации, чтобы новые материалы получали приоритет.
/**
* Выбор записей с общими тегами.
* Сортировка так, чтобы записи с несколькими совпадающими тегами были вверху.
* Вторичная сортировка по самым свежим записям.
*
* @param $post_id
* @param int $limit
* @return array
*/
function related_posts($post_id, $limit = 5) {
global $wpdb;
$query = "SELECT TOP %d x.object_id as ID
FROM (
SELECT TOP 10 tr1.object_id, COUNT(tr1.term_taxonomy_id) AS common_tag_count
FROM {$wpdb->term_relationships} AS tr1
INNER JOIN {$wpdb->term_relationships} AS tr2 ON tr1.term_taxonomy_id = tr2.term_taxonomy_id
WHERE tr2.object_id = %d
GROUP BY tr1.object_id
HAVING tr1.object_id != %d
ORDER BY COUNT(tr1.term_taxonomy_id) DESC
) x
INNER JOIN {$wpdb->posts} p ON p.ID = x.object_id
ORDER BY common_tag_count DESC, p.post_date DESC;";
$query = $wpdb->prepare($query, $limit, $post_id, $post_id);
$ids = $wpdb->get_col($query);
$posts = [];
foreach($ids as $id) {
$posts[] = get_post($id);
}
return $posts;
}
Внутренний запрос здесь используется для выбора записей с наибольшим количеством совпадающих тегов, а внешний запрос применяется для вторичной сортировки по дате публикации.
Обратите внимание, что этот запрос написан для SQL Server, поэтому некоторый синтаксис может потребовать обновления (например, TOP вместо LIMIT).
