I have a homepage displaying the home.php template, containing 2 sidebars with widgets in them.

The main query still pulls in the standard 10 posts, but since I’m not displaying these, I’d like to eliminate the query being made to the database entirely. If needs be, an empty post loop will do as I am not using the main loop in my home.php template.

How would I do this? I could use pre_get_posts to minimise and reduce the query, but that still leaves me with a very fast query, how do I eliminate it entirely?

3 s
3

The posts_request filter

Skimming through the WP_Query we find this part of interest:

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;
   }

We might try to eliminate the main home request through the posts_request filter. Here’s an example:

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 );

where we force the 'fields' => 'ids' for early exit.

The posts_pre_query filter (WP 4.6+)

We could also use the new posts_pre_querysrc filter available in WordPress 4.6+

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 );

This filter makes it possible to skip the usual database queries to implement a custom posts injection instead.

I just tested this and noticed that this will not prevent sticky posts, opposite to the posts_request approach.

Check out the ticket #36687 for more info and the example there by @boonebgorges.

Leave a Reply

Your email address will not be published. Required fields are marked *