在SQL中,随机排序是非常昂贵的操作,在非常大的站点上可能会成为一个头痛的问题。从一个类别中随机获取6个类别的帖子意味着您可能需要运行6个单独的查询,每个查询都是随机排序的。这真的会让银行破产,让你破产。
从您的回答和您所说的正在运行30个查询的事实来看,这是非常明显的。此外,真正让这项工作变得昂贵的是,帖子缩略图没有缓存用于自定义查询,因此每次查询帖子缩略图时都要进行db调用。
让trey使用不同的方法,如果我们聪明,我们可以将您的查询减少到几乎为零。这就是我们要做的
查询数据库中的所有帖子。这是我们需要聪明的地方,因为这是一个极其昂贵的操作。我们真正需要的是帖子的ID,因此我们将只查询帖子ID,这将大大减少db查询和运行查询所需的时间
一旦我们有了所有的帖子ID,我们将根据类别对它们进行排序
然后,我们将从排序后的数组中随机选取6个ID,每个类别一个,并将其传递到“main”查询,该查询将输出帖子。
前两个操作只需要2到3个查询,您可以使用诸如查询监视器之类的插件进行验证
让我们看看一些代码:(注意:所有代码都未经测试,需要PHP 5.4+)
查询
// Lets get all the post ids
$args = [
\'posts_per_page\' => -1,
\'fields\' => \'ids\' // Only get the post ID\'s
];
$ids_array = get_posts( $args );
// Make sure we have a valid array of ids
if ( $ids_array ) {
// Lets update the post term cache
update_object_term_cache( $ids_array, \'post\' );
// Loop through the post ids and create an array with post ids and terms
$id_and_term_array = [];
foreach ( $ids_array as $id ) {
// Get all the post categories
$terms = get_the_terms( $id, \'category\' );
// Make sure we have a valid array of terms
if ( $terms
&& !is_wp_error( $terms )
) {
// Loop through the terms and create our array with post ids and term
foreach ( $terms as $term )
$id_and_term_array[$term->term_id][] = $id;
}
}
// TO BE CONTINUED......
}
太好了,
$id_and_term_array
现在应该包含一个数组,其中键是term id,值是post id的数组。我们创造了所有这些,却没有打破银行。如果您选中查询监视器,您将很快看到所有这些只需要2个db调用。我们的记忆有点滥用,但我们稍后会研究一些避免耗尽记忆的方法。
选择随机ID,我们接下来要做的是循环$id_and_term_array
并从每个术语id数组中随机选取一个帖子id。我们还需要排除当前的帖子id,并需要避免重复的帖子id,如果帖子属于多个术语,我们肯定会有重复的帖子id。
因此,让我们继续我们上次放置的位置,继续
// Make sure we have a valid array
if ( $id_and_term_array ) {
// Get the current post ID
$current_post_id = get_the_ID();
// If this is a single post page, we can do
// $current_post_id = $GLOBALS[\'wp_the_query\']->get_queried_object_id();
// Lets loop through $id_and_term_array
$unique_rand_array = [];
foreach ( $id_and_term_array as $value ) {
// Shuffle the $value array to randomize it
shuffle ( $value );
// Loop through $value and get the first post id
foreach ( $value as $v ) {
// Skip the post ID if it mathes the current post or if it is a duplicate
if ( $v == $current_post_id )
continue;
if ( in_array( $v, $unique_rand_array ) )
continue;
// We have a unique id, lets store it and bail
$unique_rand_array[] = $v;
break;
}
}
}
我们现在有一个数组,其中存储了x个唯一的post id
$unique_rand_array
. 现在,我们可以将id数组传递给最终查询
最终查询
// First see if we have post ids in array
if ( $unique_rand_array ) {
// Lets run our query
$final_args = [
\'posts_per_page\' => 6,
\'post__in\' => shuffle( $unique_rand_array ), // Randomize posts
\'orderby\' => \'post__in\' // Keep post order the same as the order of post ids
];
$q = new WP_Query( $final_args );
// Lets cache our post thumbnails
update_post_thumbnail_cache( $q );
while ( $q->have_posts() ) :
$q->the_post();
?>
<div class="col-md-4">
<?php the_post_thumbnail( \'medium\', array( \'class\' => \'img-responsive\' ) );?>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</div>
<?php
endwhile;
wp_reset_postdata();
}
瞬态我们可以做的最后一件事是在瞬态中保存第一次查询的结果,因为我们不想在每次加载页面时都运行该查询。这将减少内存滥用并避免。我们还将在发布新帖子时删除我们的临时帖子
现在,让我们把一切都放在一起。
// Check if we have a transient
if ( false === ( $id_and_term_array = get_transient( \'random_term_post_ids\' ) ) ) {
// Lets get all the post ids
$args = [
\'posts_per_page\' => -1,
\'fields\' => \'ids\' // Only get the post ID\'s
];
$ids_array = get_posts( $args );
// Define the array which will hold the term and post_ids
$id_and_term_array = [];
// Make sure we have a valid array of ids
if ( $ids_array ) {
// Lets update the post term cache
update_object_term_cache( $ids_array, \'post\' );
// Loop through the post ids and create an array with post ids and terms
foreach ( $ids_array as $id ) {
// Get all the post categories
$terms = get_the_terms( $id, \'category\' );
// Make sure we have a valid array of terms
if ( $terms
&& !is_wp_error( $terms )
) {
// Loop through the terms and create our array with post ids and term
foreach ( $terms as $term )
$id_and_term_array[$term->term_id][] = $id;
}
}
}
// Set our transient for 30 days
set_transient( \'random_term_post_ids\', $id_and_term_array, 30 * DAYS_IN_SECONDS );
}
// Make sure we have a valid array
if ( $id_and_term_array ) {
// Get the current post ID
$current_post_id = get_the_ID();
// If this is a single post page, we can do
// $current_post_id = $GLOBALS[\'wp_the_query\']->get_queried_object_id();
// Lets loop through $id_and_term_array
$unique_rand_array = [];
foreach ( $id_and_term_array as $value ) {
// Shuffle the $value array to randomize it
shuffle ( $value );
// Loop through $value and get the first post id
foreach ( $value as $v ) {
// Skip the post ID if it mathes the current post or if it is a duplicate
if ( $v == $current_post_id )
continue;
if ( in_array( $v, $unique_rand_array ) )
continue;
// We have a unique id, lets store it and bail
$unique_rand_array[] = $v;
break;
}
}
// First see if we have post ids in array
if ( $unique_rand_array ) {
// Lets run our query
$final_args = [
\'posts_per_page\' => 6,
\'post__in\' => shuffle( $unique_rand_array ), // Randomize posts
\'orderby\' => \'post__in\' // Keep post order the same as the order of post ids
];
$q = new WP_Query( $final_args );
// Lets cache our post thumbnails
update_post_thumbnail_cache( $q );
while ( $q->have_posts() ) :
$q->the_post();
?>
<div class="col-md-4">
<?php the_post_thumbnail( \'medium\', array( \'class\' => \'img-responsive\' ) );?>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</div>
<?php
endwhile;
wp_reset_postdata();
}
}
最后,以下代码进入函数文件。这将在发布新帖子、删除、更新或取消删除帖子时刷新瞬态
add_action( \'transition_post_status\', function ()
{
delete_transient( \'random_term_post_ids\' );
});