web-dev-qa-db-ja.com

検索結果からページを控える方法

私は検索結果からpagesを除外したいと思い、それをする多くの方法を見つけました、そしてなぜ!is_admin()またはis_main_query()を使うか、そしてどちらがより良いのか疑問に思いました。

add_filter('pre_get_posts','search_filter');
function search_filter($query) {
    if ($query->is_search) {
        $query->set('post_type', 'post');
    }
    return $query;
}

add_filter('pre_get_posts','search_filter');   
function search_filter($query) {
    if ( !is_admin() && $query->is_search) {
        $query->set('post_type', 'post');
    }
    return $query;
}

add_action('pre_get_posts','search_filter');    
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
        if ($query->is_search) {
            $query->set('post_type', 'post');
        }
    }
}
3
SilverLink

以下を使用する場合に注意してください。

$query->set( 'post_type', 'post' );

page投稿タイプだけでなく、すべての検索可能な投稿タイプをオーバーライドします。

場合によってはそれで十分かもしれませんが、私たちのニーズに合ったいくつかのpre_get_postsスニペットを使用して完了しました。

ただし、そのようにハード修正したくない場合があります。ここでは、そのようなシナリオについて説明します。

register_post_type_argsフィルターを使用します。

投稿タイプが指定されていない場合、WP_Query検索は検索可能な投稿タイプを使用します つまり

$in_search_post_types = get_post_types( array('exclude_from_search' => false) );

投稿タイプを登録するときに、exclude_from_searchパラメーターをfalseに設定して、検索から除外できます。

page投稿タイプのセットアップ用に次のように変更できます。

add_filter( 'register_post_type_args', function( $args, $name )
{
    // Target 'page' post type
    if( 'page' === $name )
        $args['exclude_from_search'] = true;

    return $args;
}, 10, 2 );

register_post_type()の詳細 ここ

上記のフィルタリングを使用して、ページ投稿タイプが検索から除外される例は次のとおりです。

  • フロントエンドでのメインクエリ検索

    https://example.tld?s=testing
    
  • 次のようなセカンダリクエリ:

    $query = new WP_Query( [ 's' => 'testing' ] );
    
  • 次のようなセカンダリクエリ:

    $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'any' ] );
    

事前設定された投稿タイプのクエリに関する注意:

次のような投稿タイプが固定されている場合を考えてみましょう。

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page', 'post'] ] );

投稿タイプが何らかの配列$post_typeによって設定されている場合、'page'をフィルタリングして、

if( is_array( $post_type )  && count( $post_type ) > 1 )
{
    $post_type = array_filter( 
        $post_type, 
        function( $item ) { return 'page' !== $item; } 
    );
}

その配列に直接アクセスできない場合は、たとえばpre_get_postsは、WP_Queryget/setメソッドを使用して、投稿タイプの配列から「ページ」を削除します。フロントエンドのメイン検索クエリの例を次に示します。

add_action( 'pre_get_posts', function search_filter( \WP_Query $query )
{
    if( ! $query->is_search() || ! $query->is_main_query() || ! is_admin() )
        return;

    $post_type = $query->get( 'post_type' );

    if( is_array( $post_type )  && count( $post_type ) > 1 )
    {
        $post_type = array_filter( 
            $post_type, 
            function( $item ) { return 'page' !== $item; } 
        );
        $query->set('post_type', $post_type );
    }

} );

ここで配列数> 1を確認したのはなぜですか?

これは、次のような例から'page'を削除することに注意する必要があるためです。

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page' ] ] );

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page' ] );

投稿タイプの場合、空の配列または空の文字列として:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [] ] );

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => '' ] );

'post'投稿タイプにフォールバックします。

ご了承ください:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page, post' ] );

結果の投稿タイプは'pagepost'になるため、サポートされていません。

WP_Queryオブジェクトに直接アクセスできないこれらの場合、検索WHEREクエリ部分で'post__in' => []または1=0などのトリックを使用してクエリを停止するか、さらにはposts_pre_queryフィルターまたはより高度な方法を使用します。このサイトには、それに関する多くの答えがあります。 This および this は、今思い出したものです。

nullケース:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => null ] );

'any'投稿タイプにフォールバックします。

それが役に立てば幸い!

PS:

両方があるため、スニペットの不整合にも注意してください

add_filter('pre_get_posts','search_filter');   

そして

add_action('pre_get_posts','search_filter');   

これはactionと見なされますが、アクションはフィルターのように背後でラップされるため、違いはありません。

5
birgire

pre_get_postsはフロントエンドだけでなくadminでも実行されます。これを使用すると、adminユーザーに表示される投稿とフロントエンドの結果をフィルタリングできます。 ! is_admin()を追加することはそのコードがフロントエンドだけに影響することを確実にするでしょう。

is_main_query()はあなたが投稿のクエリにのみ影響を与えていることを保証します、例えばナビゲーションバーのメニューアイテムやサイドバーの投稿のリストには影響しません。それを使うことをお勧めします。

これが明らかではないかどうか私に知らせてください、

3
Ben Casey