WP_QUERY:从最近的10个帖子中随机获得3个帖子

时间:2017-03-20 作者:WebElaine

在一个有很多帖子的网站上工作,我需要显示一个特定类别的3篇帖子,但所有帖子都需要来自网站上发布的最新10篇。我可以抓取3篇完全随机的帖子(倾向于拉非常旧的帖子)或抓取10篇帖子(但我不知道如何随机排列顺序,只显示3篇)。

到目前为止,我有以下疑问:

$args = array(
    \'post_type\' => \'post\',
    \'category_name\' => \'mycategory\',
    \'posts_per_page\' => 10,
    \'orderby\' => \'date\',
    \'order\' => \'DESC\',
    \'meta_key\' => \'_thumbnail_id\',
    \'no_found_rows\' => \'true\'
);
$query = new WP_Query( $args );
此外,还尝试从查询的10篇文章中随机获得3篇文章:

$randomPosts = shuffle( $query ); 
$randomPosts = array_slice( $randomPosts, 0, 3 );
但将结果视为数组是行不通的,因为它实际上是一个对象
我唯一的另一个想法是\'posts_per_page\' = 3 具有\'orderby\' => \'rand\' 抓取3个随机帖子并添加\'date_query\' 限制在过去6个月内。这很接近,但最好将查询限制在最近的10篇帖子(可能都是3天前或5个月前发布的,它们是不均匀地同时发布的)。

最好的方法是什么
像我这样查询10篇最新帖子,然后将对象转换为数组、无序排列和切片,并将其转换回对象,或者是否有更简单、更有效的方法来实现目标?

3 个回复
最合适的回答,由SO网友:birgire 整理而成

有一种方法:

$args = [
    \'post_type\'             => \'post\',
    \'posts_per_page\'        => 10,
    \'orderby\'               => \'date\',
    \'order\'                 => \'DESC\',
    \'no_found_rows\'         => \'true\',
    \'_shuffle_and_pick\'     => 3 // <-- our custom argument
];

$query = new \\WP_Query( $args );
海关在哪里_shuffle_and_pick 此演示插件支持以下属性:

<?php
/**
 * Plugin Name: Support for the _shuffle_and_pick WP_Query argument.
 */
add_filter( \'the_posts\', function( $posts, \\WP_Query $query )
{
    if( $pick = $query->get( \'_shuffle_and_pick\' ) )
    {
        shuffle( $posts );
        $posts = array_slice( $posts, 0, (int) $pick );
    }
    return $posts;
}, 10, 2 );

SO网友:Fayaz

显然,您可以接受所有帖子,并使用PHP将结果随机化like shown in this answer. 或者,也可以使用SQL进行随机化。

在数据库中处理随机化:没有内置的WordPress函数(或参数)来实现这一点,但是,您可以使用posts_request 用于更改原始SQL查询集的筛选器WP_Query 仅从数据库中实现随机化。

您可以在活动主题的functions.php 文件或作为新的自定义插件:

<?php
/**
 *  Plugin Name: Randomize Posts
 *  Plugin URI: https://wordpress.stackexchange.com/a/260877/110572
 *  Description: Randomize posts basd on \'_randomize_posts_count\' query argument
 *  Author: Fayaz
 *  Version: 1.0
 *  Author URI: http://fmy.me/
 */

function wpse260713_randomize_posts( $sql_query, $query ) {
    $rand = (int) $query->get( \'_randomize_posts_count\' );
    if( $rand ) {
        $found_rows = \'\';
        if( stripos( $sql_query, \'SQL_CALC_FOUND_ROWS\' ) !== FALSE ) {
            $found_rows = \'SQL_CALC_FOUND_ROWS\';
            $sql_query = str_replace( \'SQL_CALC_FOUND_ROWS \', \'\', $sql_query );
        }
        $sql_query = sprintf( \'SELECT %s wp_posts.* from ( %s ) wp_posts ORDER BY rand() LIMIT %d\', $found_rows, $sql_query, $rand );
    }
    return $sql_query;
}
add_filter( \'posts_request\', \'wpse260713_randomize_posts\', 10, 2 );
然后,您可以使用以下查询:

$args = array(
    \'post_type\' => \'post\',
    \'posts_per_page\' => 10,
    \'orderby\' => \'date\',
    \'order\' => \'DESC\',
    \'meta_key\' => \'_thumbnail_id\',
    \'no_found_rows\' => \'true\',
    \'_randomize_posts_count\' => 3
);
$query = new WP_Query( $args );
比较分析:这种方法只会带来_randomize_posts_count 而不是在PHP端带来所有结果和随机化。因此,它可以更好地优化与数据库的数据通信。如果数据库服务器与web服务器分开,则效果更好。

  • If query cache is not enabled, 当显示的随机帖子数量与选择的帖子总数相差很大时,这个解决方案会更快。例如:如果您显示最近200篇文章中的3篇随机文章,那么这种方法会快得多。

  • If query cache is enabled, 然后Birgire\'s method 将更快,因为这样可以避免以后的SQL请求。然而,对于较大的样本量,它可能仍然较慢,因为您必须在查询缓存中存储大量信息。

    如果您仔细考虑样本大小并选择更适合您的用例的解决方案,则是最好的选择。

  • Note: 与常规代码相比,随机方法的速度非常慢(而且通常不可伸缩),因此无论您选择什么方法,当您的随机样本量相当大(如数千)时,都要格外小心。

    SO网友:CK MacLeod

    Fayaz和birgire的出色工作——比我可能想到的要专业得多——但我认为有一种更简单的方法,除非我不理解这个问题(很可能!):1) 使用get\\u posts()或最简单的wp\\u get\\u recent\\u posts(),它们都默认返回数组,接受wp Query$args,并默认使用no\\u found\\u rows=true,2)洗牌数组,3)然后切掉三个。

    我就是这样为自己解决了一个类似的问题,当时我几乎什么都不懂,而我现在的理解状态是我当时几乎什么都不懂。然而,birgire和Fayaz的代码很酷,所以请随意选择其中一个!

    相关推荐

    使用新的WP-Query()从循环中过滤后期格式;

    嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post