web-dev-qa-db-ja.com

検索結果ページに対してのみクエリをフィルタリングする

私は一般的な検索のために検索結果をカスタマイズしようとしています、しかしそれがsearch.phpテンプレートを使っているならば only 。私は私のサイトで他の検索をしている、そして私はこのフィルタがそれらに干渉したくない。 is_page_template('search.php')を除いて、すべて次のコードで機能します。

そのコード行を条件として入力すると、IF条件が失敗するため、通常の検索フィルタリングに戻ります。 search.phpページにいる場合にコードを実行する方法は?

    //Filter the search for only posts and parts
    function SearchFilter($query)
    {
        if ($query->is_search && is_page_template('search')) {
            $query->set('post_type', array('post', 'parts'));
            $query->set('meta_key', 'Manufacturer');
            $query->set('orderby', 'meta_value');
            $query->set('order', 'ASC');
        }
        return $query;
    }

    add_filter('pre_get_posts', 'SearchFilter');
2
Jordan Carter

追加のクエリがかかる可能性がある回避策があります。しかし@Miloは、WordPressはクエリをキャッシュすることに関してかなり賢いと言ったので、これはあなたにとって大したことではないはずです。

pre_get_posts内でクエリを実行してから、いくつかのチェックを行うことができます。状況が要件と一致した場合は、クエリをフィルタリングします。

//Filter the search for only posts and parts
function SearchFilter($query)
{
    remove_action('pre_get_posts', 'SearchFilter');
    // Run the query to fetch the results
    $posts = get_posts( $query->query );
    if(!empty($posts)) {
        // Check the template for the first post 
        if( get_page_template_slug( $posts[0]->ID ) == 'YOUR SLUG HERE' ){
            $search_template = true; 
        } else {
            $search_template = false; 
        }
    }
    // Now filter the posts
    if ($query->is_main_query() & $query->is_search && $search_template) {
        $query->set('post_type', array('post', 'parts'));
        $query->set('meta_key', 'Manufacturer');
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
    }
    return $query;
}

add_action('pre_get_posts', 'SearchFilter');
1
Jack Johansson

ステップバイステップで分解しましょう。

if ($query->is_search && is_page_template('search')) {

ここに3つの問題があります

is_page_template

search.phpはページテンプレートではなく、検索テンプレートのロード方法ではありません。だからこれはうまくいきません。

しかし、それがうまくいった場合、新しい問題があります。 is_page_templateなどの関数はメインのクエリに依存していますが、pre_get_postsフィルタに入っています。そのクエリがまだ設定されているのか、それとも他のクエリをフィルタリングしているのかわかりません。

だから我々はする必要があります:

  • is_page_templateチェックを削除してください、それはあなたがそれがすると思うことをしません
  • フィルタがウィジェットや他のクエリに干渉しないように$query->is_main_query()チェックを追加します

メソッドとメンバー変数

if ($query->is_search

これはうまくいきません、そしてあなたにはPHP警告を生成するべきです。問題はis_searchは変数ではなく関数/メソッドであるということです。

if ( $query->is_search() && $query->is_main_query() ) {

しかしsearch.php

WordPressはメインクエリに基づいてどのテンプレートをロードするかを決定します。それがメインのクエリで、is_searchがtrueの場合、search.phpがロードされます。

このため、WordPressは、フィルタが実行されたときに使用するテンプレートを決定していません。実際、あなたはWordPressにそれがどのテンプレートをロードするかを変更することができます。たとえば、すべての変数の設定を解除して単一の投稿を読み込むように指示した場合、search.phpやアーカイブはまったく取得されません。代わりにsingle.phpを取得する可能性があります。

ページテンプレートの検索クエリについて

is_main_queryはfalseになりますので、問題ありません。

1
Tom J Nowell