私はhome.php
テンプレートを表示するホームページを持っていて、そこにはウィジェットが入った2つのサイドバーがあります。
メインのクエリはまだ標準の10の投稿を引き込んでいますが、これらを表示していないので、データベースに対して行われているクエリを完全に排除したいと思います。必要に応じて、home.php
テンプレートでメインループを使用していないので、空のポストループでも問題ありません。
どのようにこれをしますか?クエリを最小化したり減らしたりするためにpre_get_posts
を使用することもできますが、それでも非常に高速なクエリが残ります。
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以上)新しいposts_pre_query
を使うこともできますsrc 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 );
このフィルタにより、通常のデータベースクエリをスキップして代わりにカスタム投稿インジェクションを実装することが可能になります。
私はこれをテストしたところ、posts_request
のアプローチとは反対に、これがスティッキーポストを防ぐことはないことに気付きました。
これは@birgireから学んだきちんとしたトリックです。SQLクエリのWHERE
句にAND where 0=1
を追加することでメインクエリを停止できます。これでも1つのdbクエリが発生する可能性がありますが、確実にメインのクエリが投稿をクエリするのを阻止します。
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';
残念ながら、私は何もテストする時間がありません、しかしこれはいい出発点であるべきです
参考までに、前: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 );