the_contentおよびis_main_query


15

フィルターでコンテンツをフィルタリングしていthe_contentます。すべてが完璧に機能しますが、私の変更はカスタムクエリにも適用されるという抜粋です。ウィジェットがカスタムクエリを使用している場合、私の変更もサイドバーに表示されます

それに対抗するために、私はis_main_query()メインクエリのみを対象にしていますが、機能していません。変更はすべてのクエリにそのまま適用されます。面白いのは、次のような他のすべての条件チェックis_single()is_category()特定のページをターゲットにすると機能することです。ただし、使用するかどうかにis_main_query()かかわらず、すべての変更はそのページの他のカスタムクエリに影響します。

ここに何かが欠けていますか?the_contentフィルターのみを使用してメインクエリに変更を適用する方法

add_filter('the_content', 'custom_content');

function custom_content($content){

    if(is_main_query()){ // << THIS IS NOT WORKING
        // My custom content that I add to the_content()    
    }
    return $content;
}

回答:


11

正直に言うと、関数in_the_loop()はあなたが探しているものです:

add_filter( 'the_content', 'custom_content' );

function custom_content( $content ) {
    if ( in_the_loop() ) {
        // My custom content that I add to the_content()    
    }
    return $content;
}

どのようなin_the_loop行いはのグローバルかどうかを確認することで$wp_query、現在のポストの(つまり、メインクエリオブジェクトである)です-1 < $current_post < $post_count

これは、メインクエリがループしているときに発生します。ループが開始される前は現在の投稿が-1であり、ループが終了すると現在の投稿は再び-1にリセットされるためです。

したがって、in_the_loop()trueの場合、メインのクエリオブジェクトがループしていることを意味しますが、これはこの場合に必要なものです(そして@ialocinが書いた答えのようloop_startloop_end、アクションを追加してon を削除した結果と同じです;実際には動作します)同じ理由で、私の+1を取得しました。

@ialocinのアプローチの利点はin_the_loop()、メインクエリに対してのみ機能するため、メインクエリオブジェクトとは異なるクエリオブジェクトをターゲットにする場合です。


私のサイト検索でもオンライン検索でも、これに出くわすことはありませんでした。機能する隠された宝石。すべてのソリューションはis_main_query、実際に誰もこれを徹底的にテストしたことはないと思います。ご意見をお寄せいただきありがとうございます、本当に感謝
Pieter Goosen 14

1
@PieterGoosenうれしいです。これは非常に古い関数であり、それが問題でis_main_queryはなかった時代からまっすぐにやって来ました。
gmazzap

ご存知のように、これは私が見逃した場所です。私は古いタイマーではありません:-)、3.3でWordpressに参加しました。
ピーターグースン14

2
@GMは、これをあなたの答えに加えてくれませんか。これは、この答えにつまずくかもしれない他の人にとって有用な情報です。私のようなほとんどの人はコメントを読まない:-)
Pieter Goosen 14

1
@PieterGoosen完了:)
gmazzap

7

これは、@ Ottoの回答への単なる追加です。少しわかりやすくするためです。基本的に@Ottoが言っていることは、ロジックを逆にする必要があります。つまり、メインクエリを確実に決定できる場合は、the_contentフィルターにフックを追加および削除できます。

たとえば、メインクエリはpre_get_postsアクションで確実に認識されるため、これは機能します。

function wpse162747_the_content_filter_callback( $content ) {
    return $content . 'with something appended';
}

add_action( 'pre_get_posts', 'wpse162747_pre_get_posts_callback' );
function wpse162747_pre_get_posts_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

不要になったフィルターを削除することになっているので、loop_endアクションはそのための適切な場所であり、その対応物として使用できると考えていますloop_start。次のようになります:

add_action( 'loop_start', 'wpse162747_loop_start_callback' );
function wpse162747_loop_start_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

add_action( 'loop_end', 'wpse162747_loop_end_callback' );
function wpse162747_loop_end_callback( $query ) {
    if ( $query->is_main_query() ) {
        remove_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

この明日をテストします。詳細な説明をありがとう。
ピーターグーセン14

いつものように私の喜び@PieterGoosen急いではありませんが、私はまだ十分ではないので、そうしてください。
ニコライ14

1
ショートコードがthe_content()内で使用されており、ショートコードがthe_content()を呼び出す別のクエリを開始し、現在の投稿オブジェクトをリセットし、ループが継続する場合はどうなりますか?すべてのフィルターが適用されます。ここでは、非常にトリッキーな、ベルin_the_loop()...ザッツはなぜ私はいつも@Nicolaiにより近づくと、彼らは、行ったようにすぐに独自のフィルタを削除するには、お勧めで保存されていない
ジョナスLundmanを

5

あなたが使用しています is_main_query()間違っています。グローバルな$ wp_query変数が再定義されていない限り、グローバルなis_main_query()関数はtrueを返します。

現在のループがメインクエリであるかどうかをthe_contentフィルター内から判断するための100%信頼できる方法はおそらくないでしょう。コンテンツフィルターはコンテンツのみをフィルターします。どのループに使用されているかを知る能力はありません。

代わりに、必要なときにフィルターを追加し、不要なときにフィルターを削除する必要があります。


これは、メインクエリ対象とする無straighforward手段が存在しないことを実際にレットダウンでthe_contentフィルタ
ピーター・グーセン

まあ、それは本当に驚くことではありません。他のフィルターと同様に、それは単にものをフィルターします。呼び出されたときに周囲のコンテキストを知りません。適切なループ内からも呼び出されない場合があります。それを伝える方法はありません。
オットー14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.