删除首页查询


8

我有一个显示home.php模板的主页,其中包含2个带有小部件的侧边栏。

主要查询仍然会提取标准的10个帖子,但是由于我没有显示这些帖子,因此我希望完全消除对数据库的查询。如果需要的话,因为我没有在home.php模板中使用主循环,所以将执行一个空的post循环。

我该怎么做?我可以使用它pre_get_posts来最小化和减少查询,但这仍然给我一个非常快速的查询,如何完全消除它呢?


1
这个问题似乎值得一读。但是,如果您问我,我将使用自己的模板,并通过设置将其设置为静态主页,因为尽管有可能,但这并不值得。在这里阅读更有趣。所有这一切,或者我完全错过了你的问题的重点。
N00B

Answers:


7

posts_request过滤器

浏览一下WP_Query我们发现的这一部分内容:

if ( !$q['suppress_filters'] ) {
    /**
     * Filter the completed SQL query before sending.
     *
     * @since 2.0.0
     *
     * @param array    $request The complete SQL query.
     * @param WP_Query &$this   The WP_Query instance (passed by reference).
     */
      $this->request = apply_filters_ref_array( 'posts_request', 
          array( $this->request, &$this ) );
   }

   if ( 'ids' == $q['fields'] ) {
       $this->posts = $wpdb->get_col( $this->request );
       $this->posts = array_map( 'intval', $this->posts );
       $this->post_count = count( $this->posts );
       $this->set_found_posts( $q, $limits );
       return $this->posts;
   }

我们可能会尝试通过posts_request过滤器消除主要的房屋要求。这是一个例子:

add_filter( 'posts_request', function( $request, \WP_Query $q )
{
    // Target main home query
    if ( $q->is_home() && $q->is_main_query() )
    {
        // Our early exit
        $q->set( 'fields', 'ids' );

        // No request
        $request = '';
    }

    return $request;    

}, PHP_INT_MAX, 2 );

我们迫使'fields' => 'ids'提早退出。

所述posts_pre_query过滤器(WP 4.6+)

我们还可以使用WordPress 4.6+中可用的新posts_pre_querysrc过滤器

add_filter( 'posts_pre_query', function( $posts, \WP_Query $q )
{
    if( $q->is_home() && $q->is_main_query() )
    {
        $posts = [];
        $q->found_posts = 0;
    }
    return $posts;
}, 10, 2 );

通过此过滤器,可以跳过常规数据库查询来实现自定义帖子注入。

我只是对此进行了测试,并注意到与posts_request方法相反,这不会阻止发贴。

查看票证#36687了解更多信息,并@boonebgorges提供示例


与我刚刚写的内容非常相似,但是我没有发现领域ID部分,因此又敲了2个查询,谢谢!
汤姆·J·诺维尔

1
好的,有时候会想到,有一个简单的方法可以很WP_Query早就退出,这很不错,例如通过类似的参数 'skip_query' => true,甚至通过过滤器,但是后来我意识到,这很容易使互联网上的网站混乱,因此很多方法;-) @TomJNowell
birgire

在行split_the_query下方有一个过滤器,其作用完全相同,但我想知道它不会减少查询的数量!
9:15 Sumit

很好的解决方案,即使我错过了'fields' => 'ids',我也经常使用它;-)
Pieter Goosen

2

这是我从@birgire中学到的一个巧妙技巧,我们可以通过将附加AND where 0=1WHERESQL查询的子句来停止主查询。这可能仍然会导致一个数据库查询,但是肯定会阻止主查询查询帖子

add_filter( 'posts_where', function ( $where, \WP_Query $q )
{
    if (    $q->is_home()
         && $q->is_main_query()
    ) {
        $where .= ' AND where 0 = 1';
    }

    return $where;
}, 10, 2 ); 

您也可以尝试将WHERE子句替换为where 0 = 1

$where = ' where 0 = 1';

代替

$where .= ' AND where 0 = 1';

不幸的是,我没有时间测试任何东西,但这应该是一个不错的起点


听起来这似乎是我所寻求的最接近的查询,或者至少是最优化的查询,在研究查询是否可以根除时,我会考虑这一点
Tom J Nowell

+1分享这个想法。但我对其进行了测试,并将其减少了2毫秒的时间:)
2016年

我希望我能记得我从那里学到的东西,但是它也被核心;-)我认为最好还是忽略粘性$q->set( 'ignore_sticky_posts', true );以防万一。
比尔吉里(Birgire),

@birgire很棒的地方。即使使用我的解决方案,您仍然可以从主要查询中获得粘性;-)
Pieter Goosen 2016年

2

供参考,之前:45q,之后:42q

该代码与@birgire使用的代码非常相似

function _tomjn_home_cancel_query( $query, \WP_Query $q ) {
    if ( !$q->is_admin() && !$q->is_feed() && $q->is_home() && $q->is_main_query() ) {
        $query = false;
        $q->set( 'fields', 'ids' );
    }
    return $query;
}
add_filter( 'posts_request', '_tomjn_home_cancel_query', 100, 2 );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.