我有一个定制后类型的‘新闻’,其中有多个自定义分类‘新闻-类别’,‘新闻标签’。每个帖子包含4-8个‘新闻标签’和1个‘新闻类别’.
对于我目前的帖子,我想显示相关的文章,基于普通的‘新闻标签’术语添加到我当前的帖子,同时也匹配‘新闻类别’术语。
因此,我希望相关的帖子寻找相同的“新闻-类别”与大多数“新闻标签”的共同术语的帖子,并按降序显示它们。
如果我展示4个相关的职位:
它们都属于同一个“新闻类别”。
这样做是可能的吗?我一直在为这件事苦苦挣扎,所以我很感激你的帮助。
发布于 2019-01-25 09:08:00
让我们将问题分成三部分:从数据库中检索相关的帖子,对它们进行排序,并显示结果。
这是可以使用分类学参数在WP_Query中提供的。
让我们首先检索当前帖子的类别并找到它们的ID:
$categories = get_the_terms( get_the_ID(), 'news-category' );
foreach ( $categories as $category ) {
$category_ids[] = $category->term_id;
}我们对标签也是这样做的:
$tags = get_the_terms( get_the_ID(), 'news-tags' );
foreach ( $tags as $tag) {
$tag_ids[] = $tag->term_id;
}然后,构建一组查询参数(稍后提供给WP_Query-call):
$related_args = array(
'post_type' => array(
'news',
),
'post_status' => 'publish',
'posts_per_page' => -1, // Get all posts
'post__not_in' => array( get_the_ID() ), // Hide current post in list of related content
'tax_query' => array(
'relation' => 'AND', // Make sure to mach both category and term
array(
'taxonomy' => 'news-category',
'field' => 'term_id',
'terms' => $category_ids,
),
array(
'taxonomy' => 'news-tags',
'field' => 'term_id',
'terms' => $tag_ids,
),
),
);最后,我们运行的查询为我们提供了一个
$related_all = new WP_Query( $related_args );请注意,此查询检索与“筛选器”匹配的所有帖子,就像我们稍后进行排序一样。如果我们现在只查询4个帖子,它们可能不是最相关的。
Sidenote:上面的查询相当重,因为它(可能)检索了大量的帖子。当我为一个客户项目创建了一个相关的帖子部分(也是一个新闻部分)时,我按日期而不是相关性来订购。这允许您设置从数据库中检索的帖子数量的限制(在您的情况下,将-1更改为4,并将'orderby' => array( 'date' => 'DESC' )添加到$related_args__-数组中)。如果您想继续对重叠进行排序,我建议您在查询参数中添加一个日期筛选器,或者将结果的数量限制在某个有限的值上,然后从该值中检索最相关的帖子。
按照前面的步骤,$related_all是一个WP_Query-object。我们按如下方式访问实际的帖子,并将它们存储在$related_all_posts中:
$related_all_posts = $related_all->posts;这为我们提供了一个更容易使用的数组。然后我们循环遍历数组中的所有结果。根据代码中的注释,在遍历结果时,我们找到与(相关的) post相关联的标记,查找它们的is,将其与前面找到的$tag_ids (主帖子)进行比较,并查看在使用array_intersect()时有多少重叠:
foreach($related_all_posts as $related_post){
// Find all tags of the related post under consideration
$related_post_tags = get_the_terms( $related_post->ID, 'news-tags' );
foreach ( $related_post_tags as $related_post_tag ) {
$related_tag_ids[] = $related_post_tag->term_id; // Save their IDs in a query
}
// Find overlap with tags of main post (in $tag_ids) using array_intersect, and save that number in
// an array that has the ID of the related post as array key.
$related_posts_commonality[$related_post->ID] = count(array_intersect($related_tag_ids, $tag_ids));
}然后,我们使用arsort()按值从高到低对最新的数组进行排序。
arsort($related_posts_commonality);最后,我们仅使用array_slice()将其限制为四篇文章:
$related_posts_commonality = array_slice($related_posts_commonality, 0, 4);您可以使用array_keys找到相关帖子的ID,例如:
$related_posts_IDs = array_keys($related_posts_commonality);要真正显示这些帖子,你可以选择两条路线。您可以使用$related_posts_commonality数组循环WP_Query (即$related_all)的结果,将匹配的帖子(按正确的顺序)保存在一个新数组中,也可以使用对象再循环一次,以供显示。因为这不需要额外的查询,所以它可能是最有效的查询。然而,这也是一种痛苦。
因此,您也可以使用我们刚刚找到的ID ($related_posts_IDs)来运行另一个查询。
$related_sorted = WP_query(array('post__in' => $related_posts_IDs));然后,您可以使用常规的循环播放 (while ($related_sorted->have_posts())等)来使用the_title()和the_content()等函数来查看和显示结果。
发布于 2021-04-23 20:47:39
由于给定的post类型共享相同的分类,常见的场景可能是根据所有分类的匹配项数(不管它们是多少或什么名称)找到相关的帖子,因此我为此创建了一个代码片段。这种方法不需要显式地定义要检查的自定义分类法(但如果需要的话也可以),而且还需要获得所有匹配项的总数,以便从最高到最低对相关的帖子进行排序。您可以修改代码段,以便只指定特定的分类法,或者更改最多应该返回多少相关帖子的限制。
这个片段有注释以供解释,但在模板中,该函数将接受当前的post ID,并返回相关帖子的post ID数组。在那里,您可以检查结果,并且假设至少找到了一些具有匹配项的其他帖子,您可以循环查看返回的相关帖子ID,然后使用ID显示关于每个帖子的任何信息(标题、链接到post等)。
基于OP问题的标题,我认为其他人可能会发现这是有用的。
下面是到代码片段的链接。
若要在单个post模板中使用此操作,请执行以下操作:
$current_post_id = get_the_id();
$related_post_ids = get_related_posts($current_post_id);
// if we have related posts...
if ( !empty($related_post_ids) ) {
foreach ( $related_post_ids as $post_id ) {
echo '' . get_the_title($post_id) . '';
}
} else {
// No related posts found
}helper函数的片段:
/**
* A WordPress helper function that takes the ID of the current post
* and returns the top three related posts ranked by highest number of taxonomy
* terms in common with the current post. Alternately, you can modify lines 26-33
* to exclude certain taxonomies so that we only check for terms in specific taxonomies
* to determine the related posts. To include up to the top X related posts instead of
* up to three, you can modify lines 149-150.
*
* In your template to make use of this function you would do something like...
*
* $current_post_id = get_the_id();
* $related_post_ids = get_related_posts($current_post_id);
*
*/
function get_related_posts($current_post_id)
{
// Get the post type we're dealing with based on the current post ID.
$post_type = get_post_type($current_post_id);
// Get all taxonomies of the specified post type of the current post.
$taxonomies = [];
$taxonomy_objects = get_object_taxonomies( $post_type, 'objects' );
foreach($taxonomy_objects as $taxonomy) {
// If you want to only check against certain taxonomies, modify this section as needed
// to set conditions for which taxonomies should be excluded or included. Below is just an example.
// if ($taxonomy->name !== 'post_format' && $taxonomy->name !== 'post_tag') {
// array_push($taxonomies, $taxonomy);
// }
// By default, we will check against all taxonomies.
array_push($taxonomies, $taxonomy);
}
// Get all the posts of the specified post type,
// excluding the current post, so that we can compare these
// against the current post.
$other_posts_args = array(
'posts_per_page' => -1,
'post_type' => $post_type,
'post__not_in' => array($current_post_id),
);
$other_posts = new WP_Query( $other_posts_args );
wp_reset_postdata();
// We will create an object for each matching post that will include
// the ID and count of the number of times it matches any taxonomy term with the current post.
// Later, when we create those, they will get pushed to this $matching_posts array.
$matching_posts = array();
// If we have other posts, loop through them and
// count matches for any taxonomy terms in common.
if($other_posts->have_posts()) {
foreach($taxonomies as $taxonomy) {
// Get the term IDs of terms for the current post
// (the post presumably displaying as a single post
// back in our template, for which were finding related posts).
$current_post_terms = get_the_terms($current_post_id, $taxonomy->name);
// Only continue if the current post actually has some terms for this taxonomy.
if($current_post_terms !== false) {
foreach($other_posts->posts as $post) {
// Get the term IDs of terms for this taxonomy
// for the other post we are currently looping over.
$other_post_terms = get_the_terms($post->ID, $taxonomy->name);
// Check that other post has terms and only continue if there
// are terms to compare.
if($other_post_terms !== false) {
$other_post_term_IDs = array();
$current_post_term_IDs = array();
// Get term IDs from each term in the current post.
foreach($current_post_terms as $term) {
array_push($current_post_term_IDs, $term->term_id);
}
// Get term IDs from each term in the other post.
foreach($other_post_terms as $term) {
array_push($other_post_term_IDs, $term->term_id);
}
if( !empty($other_post_term_IDs) && !empty($current_post_term_IDs) ) {
// Collect the matching term IDs for the terms the posts have in common.
$match_count = sizeof(array_intersect($other_post_term_IDs, $current_post_term_IDs));
// Get the ID of the other post to use to identify and store this post
// in our results.
$post_ID = $post->ID;
if ($match_count > 0) {
// Assume post not added previously.
$post_already_added = false;
// If posts have already been added to our matches
// then check to see if we already added this post.
if(!empty($matching_posts)) {
foreach($matching_posts as $post) {
// If this post was added previously then let's increment the count
// for our new matching terms.
if (isset($post->ID) && $post->ID == $post_ID) {
$post->count += $match_count;
// Switch this to true for the check we perform below.
$post_already_added = true;
}
}
// If never found a post with same ID in our $matching_posts
// list then create a new entry associated with this post and add it.
if ($post_already_added === false) {
$new_matching_post = new stdClass();
$new_matching_post->ID = $post_ID;
$new_matching_post->count = $match_count;
array_push($matching_posts, $new_matching_post);
}
} else {
// If no posts have been added yet to $matching_posts then this will be the first.
$new_matching_post = new stdClass();
$new_matching_post->ID = $post_ID;
$new_matching_post->count = $match_count;
array_push($matching_posts, $new_matching_post);
}
}
}
}
}
}
}
if(!empty($matching_posts)) {
// Sort the array in order of highest count for total terms in common
// (most related to least).
usort($matching_posts, function($a, $b) {
return strcmp($b->count, $a->count);
});
// Just take the top 3 most related
$most_related = array_slice($matching_posts, 0, 3);
// Get the IDs of most related posts.
$matching_posts = array_map(function($obj) {
return $obj->ID;
}, $most_related);
}
}
return $matching_posts;
}发布于 2022-08-23 08:10:12
我以Brams为例,但需要在两个点对代码进行调整,以便按预期运行。
( 1)每个相关_post的清除数组$related_tag_ids
foreach($related_all_posts as $related_post){
// Find all tags of the related post under consideration
$related_post_tags = get_the_terms( $related_post->ID, 'news-tags' );
$related_tag_ids = array();
foreach ( $related_post_tags as $related_post_tag ) {
$related_tag_ids[] = $related_post_tag->term_id; // Save their IDs in a query
}
// Find overlap with tags of main post (in $tag_ids) using array_intersect, and save that number in
// an array that has the ID of the related post as array key.
$related_posts_commonality[$related_post->ID] = count(array_intersect($related_tag_ids, $tag_ids));
}2)数组片,$preserve_keys设置为true
$related_posts_commonality = array_slice($related_posts_commonality, 0, true);https://wordpress.stackexchange.com/questions/326497
复制相似问题