查询不同类别的随机帖子

时间:2016-07-07 作者:cadobe

我有六个常规类别,而不是自定义类别(每个类别有5到10篇帖子),我试图在页面上显示每个类别中的一篇随机帖子。

输出的问题是获取随机帖子很好,但有些帖子是从同一类别中获取的,这是我不想要的。下面是我正在使用的代码:

$args_ = array(
    \'posts_per_page\' => 6,
    \'orderby\' => \'rand\',
    \'exclude\' => $postid , // the current post ID
    \'category\' => $cat_id_array // here is the array of categories
);

$myposts = get_posts( $args_ );
//var_dump($myposts); // I have duplicate category here

foreach ( $myposts as $post ) : setup_postdata( $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 endforeach;
wp_reset_postdata();
任何帮助都将不胜感激。

2 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

在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\' );
});

SO网友:cadobe

我只是用bueltge sugestion来修复它,比如我们:

foreach ( $cat_id_array as $cat ) :

    $args =  array( \'posts_per_page\' => 1, \'cat\' => $cat );
    $myposts = get_posts( $args );
    //var_dump($myposts);

    foreach($myposts as $posts) :
         var_dump($posts->ID);

    endforeach;
endforeach;
现在一切正常。谢谢你提醒我。我是否有机会减少此特定代码的查询数?它显示为30个查询

相关推荐

如何在WooCommerce_Account_Orders函数中传递$CURRENT_PAGE?

woocommerce功能woocommerce_account_orders($current_page) 已调用1个参数$current_page. 该函数通过调用woocommerce_account_orders_endpoint 通过以下挂钩-add_action( \'woocommerce_account_orders_endpoint\', \'woocommerce_account_orders\' );然而,在上述挂钩中,$current_page 未在函数中作为参数传递。情况如何$c