私は、ユーザーが多くの投稿メタを検索できるようにする検索機能を備えたWebサイトに取り組んでいます。強制的に結果を返さないようにしたい特定の検索パターンがあります。 WP_Queryは技術的にはデータベースで結果を見つけるでしょうが、どうにかしてそれをオーバーライドしてif( $example->have_posts() )
を失敗させるために結果を返さないよう強制したいのです。
'force_no_results' => true
のように、結果を返さないように強制するような、WP_Queryに渡すことができるある種のパラメーターはありますか?
やってみる
'post__in' => array(0)
シンプルで要点に。
奇妙なことに、WP_Query
をショートさせる明確で明確な方法はありません。
もしそれが main queryでWP->parse_request()
の周りに何か問題があるかもしれないなら、比較的最近の(3.5)do_parse_request
フィルタがあるようです。
しかし、WP_Query
自体には、AND 1=0
フィルターを介したposts_where
の追加によるSQLクエリの短絡など、通常ダーティーハックが秩序だっています。
クエリパラメータを存在しない値に設定する際の問題は2です。
'posts_*'
フィルタフック('posts_where'
、'post_join'
など)があるため、クエリに存在しないparamを設定しても結果が返されないこと、フィルタによって返される単純なOR
句が何かを返すことを確認できません。 。確実 /クエリが結果を返さず、パフォーマンス上の問題がまったくない(または最小限になる)ためには、少し{hardcoreルーチンが必要です。
そのルーチンを起動するには、すべてのメソッドを使用できます。技術的には、存在しないイベント引数WP_Query
に任意の引数を渡すことができます。
あなたが'force_no_results' => true
のようなものが好きなら、あなたはそれをそのように使うことができます:
$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );
そして'pre_get_posts'
上で実行されるコールバックを追加します。
add_action( 'pre_get_posts', function( $q ) {
if (array_key_exists('force_no_results', $q->query) && $q->query['force_no_results']) {
$q->query = $q->query_vars = array();
$added = array();
$filters = array(
'where', 'where_paged', 'join', 'join_paged', 'groupby', 'orderby', 'distinct',
'limits', 'fields', 'request', 'clauses', 'where_request', 'groupby_request',
'join_request', 'orderby_request', 'distinct_request','fields_request',
'limits_request', 'clauses_request'
);
// remove all possible interfering filter and save for later restore
foreach ( $filters as $f ) {
if ( isset($GLOBALS['wp_filter']["posts_{$f}"]) ) {
$added["posts_{$f}"] = $GLOBALS['wp_filter']["posts_{$f}"];
unset($GLOBALS['wp_filter']["posts_{$f}"]);
}
}
// be sure filters are not suppressed
$q->set( 'suppress_filters', FALSE );
$done = 0;
// use a filter to return a non-sense request
add_filter('posts_request', function( $r ) use( &$done ) {
if ( $done === 0 ) { $done = 1;
$r = "SELECT ID FROM {$GLOBALS['wpdb']->posts} WHERE 0 = 1";
}
return $r;
});
// restore any filter that was added and we removed
add_filter('posts_results', function( $posts ) use( &$done, $added ) {
if ( $done === 1 ) { $done = 2;
foreach ( $added as $hook => $filters ) {
$GLOBALS['wp_filter'][$hook] = $filters;
}
}
return $posts;
});
}
}, PHP_INT_MAX );
このコードが行うことは、できるだけ遅く'pre_get_posts'
で実行されます。引数 'force_no_results'がクエリに存在する場合は、次のようになります。
SELECT ID FROM wp_posts WHERE 0 = 1
すべてのフィルタが削除されると、このクエリが変更される可能性はなく、非常に高速であり、確実な結果は得られません。