没有本机方法可以实现这一点,因此需要运行多个查询才能实现这一点。如果做得不正确,这可能会变得非常昂贵,因此我们需要在这里保持聪明。
我在这里想到了一些想法,这似乎是有道理的,所以下面是我们将要做的
为每个学期运行一个查询,以获取每个学期我们想要的帖子数量。为了尽可能精简,并真正节省db调用和时间,我们将只获取post ID
从所有这些查询中,我们将构建一个ID数组。如果一篇文章属于两个术语,我们还需要删除重复项
一旦我们有了一个post ID数组,我们将运行最终查询以获得完整的post对象
我决定创建一个函数来收集帖子ID,然后在一个瞬态中保存所有内容,每当创建新帖子,或者更新、删除或取消删除帖子时,我们都会刷新该瞬态。这样,您可以使查询更加精简。在一天结束时,该函数在不到0.005s的时间内只需要2个db调用,因此它在性能方面确实更有意义
函数中的所有内容都有很好的注释,因此请确保在进行过程中遵循注释:(NOTE: 此答案中的所有代码至少需要PHP 5.4)
/**
* Function to get an array of post ID\'s according to term and according
* to a specific amount of posts per page set per term
*
* @param (string) $post_type
* @param (string) $taxonomy
* @param (array) $args
* @return (array) $output_ids
*/
function get_unique_ppp_per_category( $post_type = \'post\', $taxonomy = \'category\', $args = [] )
{
// Make sure we have a post type and taxonomy and sanitize it
if ( !$post_type
|| !$taxonomy
)
return false;
if ( $post_type !== \'post\' )
$post_type = filter_var( $post_type, FILTER_SANITIZE_STRING );
// Make sure we have a valid taxonomy to avoid bugs
if ( $taxonomy !== \'category\'
|| $taxonomy !== \'post_tag\'
) {
// Santitize and validate the taxonomy
$taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );
// Check if taxonomy exist, if not, return false
if ( !taxonomy_exists( $taxonomy ) )
return false;
}
// If $args are empty or not an array, return false
if ( !$args
|| !is_array( $args )
) {
return false;
}
// Set a transient to store the post ID\'s. Excellent for performance
if ( false === ( $output_ids = get_transient ( \'term_id_list_\' . md5( $post_type . $taxonomy . json_encode( $args ) ) ) ) ) {
// Set up a variable to hold an array of post id and id that should not be duplicated
$post_ids = [];
/**
* Loop through the $args array and build our queries
*
* We need to make sure that every value, $arg, is an array.
* That array should have the term id as key and posts per page value
* as value, so in short, the setup should be \'(int) term ID => (int) posts_per_page\'
* If not, we will simply continue. You should however build in some kind of
* error notice on this as it can and will make debugging easier
*/
foreach ( $args as $term_id=>$ppp ) {
// Sanitize and validate our values
$ppp = filter_var( $ppp, FILTER_VALIDATE_INT );
$term_id = filter_var( $term_id, FILTER_VALIDATE_INT );
/**
* Create a flat array of post ID\'s that we should not duplicate
*
* @see array_walk_recursive
*/
$duplicates = [];
if ( $post_ids ) {
array_walk_recursive( $post_ids, function ( $a ) use ( &$duplicates )
{
$duplicates[] = $a;
});
}
// Set up our query args
$query_args = [
\'fields\' => \'ids\', // Get only post ids to make this very quick
\'post_type\' => $post_type,
\'posts_per_page\' => $ppp,
\'post__not_in\' => $duplicates, // Do not duplicate these posts
\'tax_query\' => [
[
\'taxonomy\' => $taxonomy,
\'terms\' => $term_id,
\'include_children\' => false
]
],
// Add any extra parameters here
];
$q = get_posts( $query_args );
$post_ids[] = $q;
} // endforeach $args
/**
* Flattern the nested array of post ID\'s
*
* @see array_walk_recursive
*/
$output_ids = [];
if ( $post_ids ) {
array_walk_recursive( $post_ids, function ( $a ) use ( &$output_ids )
{
$output_ids[] = $a;
});
}
set_transient( \'term_id_list_\' . md5( $post_type . $taxonomy . json_encode( $args ) ), $output_ids, 30*DAY_IN_SECONDS );
}
return $output_ids;
}
用法根据示例,您需要类别1中的7篇帖子、类别3中的10篇帖子和类别7中的13篇帖子。该函数有三个参数,第一个是post类型,第二个是分类法,第三个是键/值对数组,其中键是类别ID,值是特定类别的post数量
因此,在本例中,我们将使用内置类型post
以及内置分类法category
EXAMPLE
$args = [
//\'category ID\' => \'posts_per_page\',
1 => 7,
3 => 10,
7 => 13
];
$q = get_unique_ppp_per_category( \'post\', \'category\', $args );
var_dump( $q );
现在我们可以通过
$q
到适当的
WP_Query
. 在我们做之前只需要做几点笔记
如果您需要在将类别传递给get_unique_ppp_per_category
函数,则需要设置orderby
中的参数WP_Query
到post__in
记住,如果你的帖子类型不是post
, 记住设置post_type
以及参数
现在让我们来完成我们的帖子
if ( $q ) {
$query_args = [
\'post__in\' => $q,
\'posts_per_page\' => -1,
\'orderby\' => \'post__in\',
\'order\' => \'ASC\'
];
$the_query = new WP_Query( $query_args );
while ( $the_query->have_posts() ) {
$the_query->the_post();
// Your template tags and html markup, like
the_title();
} // endwhile
wp_reset_postdata();
} // endif $q
我们只剩下在发布新帖子或删除、取消删除或更新帖子时刷新瞬态。我们将使用
transition_post_status
适合账单的钩子
add_action( \'transition_post_status\', function ()
{
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient%_term_id_list_%\')" );
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient_timeout%_term_id_list_%\')" );
});