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?
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_query
src 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.