web-dev-qa-db-ja.com

search.phpのtemplate_includeにより、Wordpressはホームページ上でそのことを考えます。

私はカスタムタグ検索機能を持っていて、それは人々が関連する投稿を返すために複数のタグを検索することを可能にする。 「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_homeis_front_pageの条件式はすべてtrueになりますが、そうではありません。これを検索テンプレートにしたいのですが。

&sをクエリ文字列に追加すると、これは可能なことですが、やや醜い方法ですが。何か洞察がありますか?

3
Shawn Wernig

問題は、WP_Query::$is_pageWP_Query::$is_singleWP_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クエリを変更する場合も、クエリを返す必要はありません。

6
gmazzap

以下を試してください。

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'をそれほど見にくい方法で追加しました

0
chifliiiii