WordPress:首先对与标签相关的 X 个帖子进行税务查询,如果与标签相关的内容不够,则按类别进行查询
WordPress: tax query of X number of posts related by tag first, then by category if not enough in tag-related
问题
如何先输出tag related posts,然后如果tag related posts少于4个,则用category related posts填充其余4个点?
场景
有时 post 的标签很少,或者它所标记的标签很少 post。当输出 "related posts by tag," 时,该区域要么非常稀疏,只有 1 或 2 posts,要么完全是空的。
要解决这个问题,最好显示相关类别的 post,如果没有足够的标签相关 post 来满足 posts_per_page => X
。
所以,像这样:
场景 A -- 如果存在超过 4 个标签相关 post,则:
Related Posts:
Show the below posts:
1. tag-related post #1
2. tag-related post #2
3. tag-related post #3
4. tag-related post #4
Do Not show the below posts:
5. tag-related post #5
6. tag-related post #6
7. tag-related post #7
...
场景 B -- 如果只有 2 个标签相关 post 存在,则:
Related Posts:
Show the below posts:
1. tag-related post #1
2. tag-related post #2
3. category-related post #1
4. category-related post #2
Do Not show the below posts:
5. category-related post #3
6. category-related post #4
7. category-related post #5
...
我试过的
我正在使用的税务查询:
// start of the tax_query arguments
$args = array( 'posts_per_page'=>4, 'post__not_in' => array($post->ID), 'tax_query' => array( 'relation' => 'OR' ) );
// get current post tags
$tags = wp_get_object_terms( $post->ID, 'post_tag', array( 'fields' => 'ids' ) );
if ( !empty( $tags ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'field' => 'id',
'terms' => $tags
);
}
// get current post categories
$categories = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );
if ( !empty( $categories ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => $categories
);
}
// the query
$related_query = new WP_Query( $args );
据我了解,税务查询显示 "get posts that are in the same categories, then get posts that are in the same tags, then output posts until 4 are on screen."
但它始终首先输出类别 posts(其中有很多)满足 4 posts on screens 规则并遗漏了最重要的标签相关 posts。我试过移动代码,使用 AND
而不是 OR
,但不管怎样,这对我来说没有任何意义。
我也看过这些 post:WordPress - producing a list of posts filtered by tag and then category and ,但它们是关于输出按标签和类别过滤的 post 列表。我需要 posts 首先按标签关联,如果 4 个或更多,则只输出前 4 个。如果小于 4,则输出最多与类别相关的 posts 以满足 4 posts 标准。
显然我误解了查询 and/or 的问题,所以任何帮助将不胜感激。
我终于搞定了。以下函数将显示最多 4 个相关的 post,首先按标签,然后是类别,然后是自定义 post 类型,然后是任何 post if none 前 3 个条件匹配任何 posts.
function get_max_related_posts( $recent_posts = array(), $taxonomy_1 = 'post_tag', $taxonomy_2 = 'category', $total_posts = 4 ) {
// First, make sure we are on a single page, if not, bail
if ( !is_single() )
return false;
// Sanitize and vaidate our incoming data
if ( 'post_tag' !== $taxonomy_1 ) {
$taxonomy_1 = filter_var( $taxonomy_1, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy_1 ) )
return false;
}
if ( 'category' !== $taxonomy_2 ) {
$taxonomy_2 = filter_var( $taxonomy_2, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy_2 ) )
return false;
}
if ( 4 !== $total_posts ) {
$total_posts = filter_var( $total_posts, FILTER_VALIDATE_INT );
if ( !$total_posts )
return false;
}
// Everything checks out and is sanitized, lets get the current post
$current_post = sanitize_post( $GLOBALS['wp_the_query']->get_queried_object() );
// Lets get the first taxonomy's terms belonging to the post
$terms_1 = get_the_terms( $current_post, $taxonomy_1 );
// Set a varaible to hold the post count from first query
$count = 0;
// Set a variable to hold the results from query 1
$q_1 = [];
// Set a variable to hold the exclusions
$sticky = get_option( 'sticky_posts' );
$exclude = array_merge( [$current_post->ID], $sticky );
$exclude = array_merge( $exclude, $recent_posts );
// Make sure we have terms
if ( $terms_1 ) {
// Lets get the term ID's
$term_1_ids = wp_list_pluck( $terms_1, 'term_id' );
// Lets build the query to get related posts
$args_1 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $total_posts,
'fields' => 'ids',
'tax_query' => [
[
'taxonomy' => $taxonomy_1,
'terms' => $term_1_ids,
'include_children' => false
]
],
];
$q_1 = get_posts( $args_1 );
// Update our counter
$count = count( $q_1 );
// Update our counter
$exclude = array_merge( $exclude, $q_1 );
}
// We will now run the second query if $count is less than $total_posts
if ( $count < $total_posts ) {
$terms_2 = get_the_terms( $current_post, $taxonomy_2 );
// Make sure we have terms
if ( $terms_2 ) {
// Lets get the term ID's
$term_2_ids = wp_list_pluck( $terms_2, 'term_id' );
// Calculate the amount of post to get
$diff = $total_posts - $count;
$args_2 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
'tax_query' => [
[
'taxonomy' => $taxonomy_2,
'terms' => $term_2_ids,
'include_children' => false
]
],
];
$q_2 = get_posts( $args_2 );
if ( $q_2 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_2 );
// Update our post counter
$count = count( $q_1 );
// Update our counter
$exclude = array_merge( $exclude, $q_2 );
}
}
}
// We will now run the third query if $count is less than $total_posts
if ( $count < $total_posts ) {
// Calculate the amount of post to get
$diff = $total_posts - $count;
$args_3 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
];
$q_3 = get_posts( $args_3 );
if ( $q_3 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_3 );
} else {
$args_4 = [
'post_type' => 'any',
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
];
$q_4 = get_posts( $args_4 );
if ( $q_4 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_4 );
}
}
}
// Make sure we have an array of ID's
if ( !$q_1 )
return false;
// Run our last query, and output the results
$final_args = [
'ignore_sticky_posts' => 1,
'post_type' => 'any',
'posts_per_page' => count( $q_1 ),
'post__in' => $q_1,
'order' => 'ASC',
'orderby' => 'post__in',
'suppress_filters' => true,
'no_found_rows' => true
];
$final_query = new WP_Query( $final_args );
return $final_query;
}
问题
如何先输出tag related posts,然后如果tag related posts少于4个,则用category related posts填充其余4个点?
场景
有时 post 的标签很少,或者它所标记的标签很少 post。当输出 "related posts by tag," 时,该区域要么非常稀疏,只有 1 或 2 posts,要么完全是空的。
要解决这个问题,最好显示相关类别的 post,如果没有足够的标签相关 post 来满足 posts_per_page => X
。
所以,像这样:
场景 A -- 如果存在超过 4 个标签相关 post,则:
Related Posts:
Show the below posts:
1. tag-related post #1
2. tag-related post #2
3. tag-related post #3
4. tag-related post #4
Do Not show the below posts:
5. tag-related post #5
6. tag-related post #6
7. tag-related post #7
...
场景 B -- 如果只有 2 个标签相关 post 存在,则:
Related Posts:
Show the below posts:
1. tag-related post #1
2. tag-related post #2
3. category-related post #1
4. category-related post #2
Do Not show the below posts:
5. category-related post #3
6. category-related post #4
7. category-related post #5
...
我试过的
我正在使用的税务查询:
// start of the tax_query arguments
$args = array( 'posts_per_page'=>4, 'post__not_in' => array($post->ID), 'tax_query' => array( 'relation' => 'OR' ) );
// get current post tags
$tags = wp_get_object_terms( $post->ID, 'post_tag', array( 'fields' => 'ids' ) );
if ( !empty( $tags ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'field' => 'id',
'terms' => $tags
);
}
// get current post categories
$categories = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );
if ( !empty( $categories ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => $categories
);
}
// the query
$related_query = new WP_Query( $args );
据我了解,税务查询显示 "get posts that are in the same categories, then get posts that are in the same tags, then output posts until 4 are on screen."
但它始终首先输出类别 posts(其中有很多)满足 4 posts on screens 规则并遗漏了最重要的标签相关 posts。我试过移动代码,使用 AND
而不是 OR
,但不管怎样,这对我来说没有任何意义。
我也看过这些 post:WordPress - producing a list of posts filtered by tag and then category and
显然我误解了查询 and/or 的问题,所以任何帮助将不胜感激。
我终于搞定了。以下函数将显示最多 4 个相关的 post,首先按标签,然后是类别,然后是自定义 post 类型,然后是任何 post if none 前 3 个条件匹配任何 posts.
function get_max_related_posts( $recent_posts = array(), $taxonomy_1 = 'post_tag', $taxonomy_2 = 'category', $total_posts = 4 ) {
// First, make sure we are on a single page, if not, bail
if ( !is_single() )
return false;
// Sanitize and vaidate our incoming data
if ( 'post_tag' !== $taxonomy_1 ) {
$taxonomy_1 = filter_var( $taxonomy_1, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy_1 ) )
return false;
}
if ( 'category' !== $taxonomy_2 ) {
$taxonomy_2 = filter_var( $taxonomy_2, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy_2 ) )
return false;
}
if ( 4 !== $total_posts ) {
$total_posts = filter_var( $total_posts, FILTER_VALIDATE_INT );
if ( !$total_posts )
return false;
}
// Everything checks out and is sanitized, lets get the current post
$current_post = sanitize_post( $GLOBALS['wp_the_query']->get_queried_object() );
// Lets get the first taxonomy's terms belonging to the post
$terms_1 = get_the_terms( $current_post, $taxonomy_1 );
// Set a varaible to hold the post count from first query
$count = 0;
// Set a variable to hold the results from query 1
$q_1 = [];
// Set a variable to hold the exclusions
$sticky = get_option( 'sticky_posts' );
$exclude = array_merge( [$current_post->ID], $sticky );
$exclude = array_merge( $exclude, $recent_posts );
// Make sure we have terms
if ( $terms_1 ) {
// Lets get the term ID's
$term_1_ids = wp_list_pluck( $terms_1, 'term_id' );
// Lets build the query to get related posts
$args_1 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $total_posts,
'fields' => 'ids',
'tax_query' => [
[
'taxonomy' => $taxonomy_1,
'terms' => $term_1_ids,
'include_children' => false
]
],
];
$q_1 = get_posts( $args_1 );
// Update our counter
$count = count( $q_1 );
// Update our counter
$exclude = array_merge( $exclude, $q_1 );
}
// We will now run the second query if $count is less than $total_posts
if ( $count < $total_posts ) {
$terms_2 = get_the_terms( $current_post, $taxonomy_2 );
// Make sure we have terms
if ( $terms_2 ) {
// Lets get the term ID's
$term_2_ids = wp_list_pluck( $terms_2, 'term_id' );
// Calculate the amount of post to get
$diff = $total_posts - $count;
$args_2 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
'tax_query' => [
[
'taxonomy' => $taxonomy_2,
'terms' => $term_2_ids,
'include_children' => false
]
],
];
$q_2 = get_posts( $args_2 );
if ( $q_2 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_2 );
// Update our post counter
$count = count( $q_1 );
// Update our counter
$exclude = array_merge( $exclude, $q_2 );
}
}
}
// We will now run the third query if $count is less than $total_posts
if ( $count < $total_posts ) {
// Calculate the amount of post to get
$diff = $total_posts - $count;
$args_3 = [
'post_type' => $current_post->post_type,
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
];
$q_3 = get_posts( $args_3 );
if ( $q_3 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_3 );
} else {
$args_4 = [
'post_type' => 'any',
'post__not_in' => $exclude,
'posts_per_page' => $diff,
'fields' => 'ids',
];
$q_4 = get_posts( $args_4 );
if ( $q_4 ) {
// Merge the two results into one array of ID's
$q_1 = array_merge( $q_1, $q_4 );
}
}
}
// Make sure we have an array of ID's
if ( !$q_1 )
return false;
// Run our last query, and output the results
$final_args = [
'ignore_sticky_posts' => 1,
'post_type' => 'any',
'posts_per_page' => count( $q_1 ),
'post__in' => $q_1,
'order' => 'ASC',
'orderby' => 'post__in',
'suppress_filters' => true,
'no_found_rows' => true
];
$final_query = new WP_Query( $final_args );
return $final_query;
}