私はカスタムタグ検索機能を持っていて、それは人々が関連する投稿を返すために複数のタグを検索することを可能にする。 「Wordpress」と「Tutorials」の両方のタグが付いた投稿を見たいとしましょう。私はtemplate_include
フィルタを使っています。
public static function template_redirect( $template ) {
if( isset($_GET['tag-search']) )
{
$template = locate_template( array(
'search.php',
'archive.php',
'index.php'
));
}
return $template;
}
tag-search
変数は分類法の名前を保持しています。それが設定されているかどうかをチェックし、検索が実行されていることを示します。
この時点で、template
はsearch.phpに解決されます。それはいいですね。
pre_get_posts
アクションで、返される投稿を選択されたタグだけに変更するためにtax_query
を追加し、is_search
をtrueに、そしてis_home
をfalseに設定します。これが私のpre_get_posts
アクションです。
public static function pre_get_posts($query) {
if( !isset($_GET['tag-search']) || !isset($_GET['terms']) ) return $query;
if( strtolower( $_GET['method'] ) == 'and' )
{
$query->set( 'tax_query', array(
array(
'taxonomy' => $_GET['tag-search'],
'field' => 'slug',
'terms' => explode(',', $_GET['terms']),
'operator' => 'AND'
)
) );
}
else
{
$query->set( 'tax_query', array(
array(
'taxonomy' => $_GET['tag-search'],
'field' => 'slug',
'terms' => explode(',', $_GET['terms'])
)
) );
}
$query->is_search = true;
$query->is_home = false;
return $query;
}
しかし、検索を実行すると、ボディクラスは 'home'になり、is_home
とis_front_page
の条件式はすべてtrueになりますが、そうではありません。これを検索テンプレートにしたいのですが。
&s
をクエリ文字列に追加すると、これは可能なことですが、やや醜い方法ですが。何か洞察がありますか?
問題は、WP_Query::$is_page
、WP_Query::$is_single
、WP_Query::$is_archive
など、必要なすべてのクエリ変数をリセットしていないことです。
また、メインクエリとセカンダリクエリのすべてに対して'pre_get_posts'
が起動されるため、メインクエリで作業していることを確認する必要があります。
最後に、$_GET
からデータを取得する場合、使用する前にサニタイズする必要があります。良い方法は filter_input()
または filter_input_array()
を使用することです。
メソッドは次のように表示されます。
public static function pre_get_posts($query)
{
$data = filter_input_array(INPUT_GET, array(
'tag-search' => FILTER_SANITIZE_STRING,
'terms' => FILTER_SANITIZE_STRING,
'method' => FILTER_SANITIZE_STRING,
));
if( $query->is_main_query() && !empty($data['tag-search']) && !empty($data['terms']) ) {
$query->init(); // this resets ALL vars
$query->is_search = true;
// set tax query array
$tax_query = array(
'taxonomy' => $data['tag-search'],
'field' => 'slug',
'terms' => explode(',', $data['terms']),
);
// is AND method?
if( strtolower( $data['method'] ) === 'and' ) {
$tax_query['operator'] = 'AND';
}
// set tax query
$query->set( 'tax_query', array($tax_query) );
}
}
そうすることで、notテンプレートをフィルタリングする必要があります(したがって、template_redirect()
メソッドを削除できます):search.php
はWordPressは、クエリを検索として正しく認識するためです。
PS:'pre_get_post'
はactionであり、フィルターではないため、do n'tクエリを変更する場合も、クエリを返す必要はありません。
以下を試してください。
public static function pre_get_posts($query) {
if( !isset($_GET['tag-search']) || !isset($_GET['terms']) ) return $query;
if ( ! is_admin() && $query->is_main_query() ) {
if( strtolower( $_GET['method'] ) == 'and' )
{
$query->set( 'tax_query', array(
array(
'taxonomy' => $_GET['tag-search'],
'field' => 'slug',
'terms' => explode(',', $_GET['terms']),
'operator' => 'AND'
)
) );
}
else
{
$query->set( 'tax_query', array(
array(
'taxonomy' => $_GET['tag-search'],
'field' => 'slug',
'terms' => explode(',', $_GET['terms'])
)
) );
}
$query->set('s', '' );
$query->is_search = true;
$query->is_home = false;
}
return $query;
}
私はいくつかの余分なチェックと 's'をそれほど見にくい方法で追加しました