the_content und is_main_query

15

Ich filtere den Inhalt mit dem the_contentFilter. Alles funktioniert einwandfrei, auszugsweise werden meine Änderungen auch auf benutzerdefinierte Abfragen angewendet. Meine Änderungen werden auch in der Seitenleiste angezeigt, wenn das Widget eine benutzerdefinierte Abfrage verwendet

Um dem entgegenzuwirken, ziele ich nur is_main_query()auf die Hauptabfrage ab, aber sie funktioniert nicht. Änderungen werden einfach noch auf alle Abfragen durchgespielt. Was aber lustig ist, alle anderen bedingten Überprüfungen mögen is_single()und is_category()funktionieren, wenn ich auf bestimmte Seiten ziele, mit der Ausnahme, dass sich alle Änderungen auf jede andere benutzerdefinierte Abfrage auf dieser Seite auswirken, unabhängig davon, ob ich sie verwende is_main_query()oder nicht

Vermisse ich hier etwas? Wie wende ich meine Änderungen nur mit dem the_contentFilter auf die Hauptabfrage an?

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;
}
Pieter Goosen
quelle

Antworten:

11

Um ehrlich zu sein, ist die Funktion genau das, in_the_loop()was Sie suchen:

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;
}

Es in_the_loopwird geprüft, ob global für $wp_query(das ist das Hauptabfrageobjekt) des aktuellen Beitrags -1 < $current_post < $post_count.

Dies geschieht, wenn die Hauptabfrage eine Schleife durchläuft, da der aktuelle Beitrag vor dem Start der Schleife -1 ist und der aktuelle Beitrag nach dem Ende der Schleife wieder auf -1 zurückgesetzt wird.

Wenn dies in_the_loop()zutrifft, bedeutet dies, dass sich das Hauptabfrageobjekt in einer Schleife befindet. In diesem Fall ist dies das gleiche Ergebnis wie beim Hinzufügen loop_startund Entfernen der Aktion loop_end, wie es die Antwort @ialocin geschrieben hat. Tatsächlich funktioniert es aus dem gleichen Grund und bekam meine +1).

Der @ ialocin-Ansatz bietet den Vorteil, dass Sie ein anderes Abfrageobjekt als das Hauptobjekt als Ziel angeben möchten, da in_the_loop()nur die Hauptabfrage möglich ist.

gmazzap
quelle
Bei keiner meiner Website-Suchen oder Online-Suchen bin ich auf dieses Ergebnis gestoßen. Ein verstecktes Juwel, das funktioniert. Jede Lösung nutzt is_main_query, glaube wirklich, niemand hat dies gründlich getestet. Vielen Dank für Ihre Eingabe, sehr geschätzt
Pieter Goosen
1
@PieterGoosen Froh, dass es funktioniert. Das ist eine sehr alte Funktion, die direkt aus Zeiten stammt, in denen is_main_queryes nichts gab.
gmazzap
Sie sehen, hier habe ich es verpasst, ich bin kein Oldtimer :-), trat Wordpress in 3.3 bei.
Pieter Goosen
2
@ GM würde es Ihnen etwas ausmachen, dies zu Ihrer Antwort hinzuzufügen. Dies ist eine nützliche Information für andere, die über diese Antwort stolpern könnten. Die meisten Leute, wie ich, lesen keine Kommentare :-)
Pieter Goosen
1
@PieterGoosen fertig :)
gmazzap
7

Dies ist nur eine Ergänzung zu @ Ottos Antwort. Nur um es ein bisschen verständlicher zu machen. Grundsätzlich müssen Sie die Logik von @Otto umkehren. Das heißt: Wenn Sie die Hauptabfrage zuverlässig ermitteln können, können Sie Ihre Einbindung in den the_contentFilter hinzufügen und entfernen .

Beispielsweise kann die Hauptabfrage bei der pre_get_postsAktion zuverlässig erkannt werden , so dass dies funktionieren würde:

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' );
    }
}

Da Sie den Filter entfernen sollen, wenn er nicht mehr benötigt wird, denke ich, dass die loop_endAktion ein guter Ort dafür sein sollte und als Gegenstück wir ihn verwenden können loop_start. Welches würde so aussehen:

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' );
    }
}
Nicolai
quelle
Werde das morgen testen. Vielen Dank für Ihre ausführliche Erklärung.
Pieter Goosen
Es ist mir ein Vergnügen wie immer @PieterGoosen Keine Eile, aber mach es, weil ich es nicht habe - zumindest nicht genug.
Nicolai
1
Was passiert, wenn ein Shortcode in the_content () verwendet wird und der Shortcode eine andere Abfrage startet, die the_content () aufruft, das aktuelle Post-Objekt zurücksetzt und die Schleife fortgesetzt wird? Alle Filter werden angewendet. Ziemlich knifflig hier, nicht von der Glocke in_the_loop () gespeichert ... Deshalb schlage ich vor, eindeutige Filter immer zu entfernen, sobald sie fertig sind, wie von @Nicolai
Jonas Lundman,
5

Sie verwenden is_main_query()falsch. Die globale Funktion is_main_query () gibt true zurück, sofern die globale Variable $ wp_query nicht neu definiert wurde.

Es gibt wahrscheinlich keine hundertprozentig zuverlässige Möglichkeit, innerhalb eines the_content-Filters festzustellen, ob die aktuelle Schleife, in der Sie sich befinden, die Hauptabfrage ist oder nicht. Der Inhaltsfilter filtert nur den Inhalt. Es gibt keine Möglichkeit zu wissen, für welche Schleife es verwendet wird.

Fügen Sie stattdessen Ihren Filter hinzu, wenn Sie ihn benötigen, und entfernen Sie ihn, wenn Sie ihn nicht benötigen.

Otto
quelle
Tatsächlich ist es eine Enttäuschung, dass es keine eindeutigen Mittel gibt, um die Hauptabfrage mit the_contentFilter
Pieter Goosen,
Nun, das ist aber nicht wirklich überraschend. Wie bei jedem anderen Filter werden nur die Dinge gefiltert. Es kennt den Kontext, in dem es aufgerufen wird, nicht. Es kann sein, dass es nicht einmal aus einer richtigen Schleife heraus aufgerufen wird. Keine Möglichkeit, es zu sagen.
Otto