the_content i is_main_query

15

Filtruję zawartość za pomocą the_contentfiltra. Wszystko działa idealnie, fragment, że moje zmiany są również stosowane do niestandardowych zapytań. Moje zmiany pojawiają się również na pasku bocznym, jeśli widżet korzysta z niestandardowego zapytania

Aby temu przeciwdziałać, używam tylko is_main_query()do kierowania zapytania głównego, ale to nie działa. Zmiany są po prostu nadal stosowane do wszystkich zapytań. Co zabawne, wszystkie inne kontrole warunkowe lubią is_single()i is_category()działają, jeśli kieruję reklamy na określone strony, z wyjątkiem tego, że wszystkie zmiany wpływają na wszelkie inne niestandardowe zapytania na tej stronie, niezależnie od tego, czy używam, is_main_query()czy nie

Czy coś mi umyka. Jak zastosować zmiany do głównego zapytania tylko przy użyciu the_contentfiltra

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
źródło

Odpowiedzi:

11

Szczerze mówiąc, funkcja in_the_loop()jest tym, czego szukasz:

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

Co in_the_looppolega na sprawdzeniu, czy globalny $wp_query(to jest główny obiekt zapytania) bieżącego postu jest -1 < $current_post < $post_count.

Dzieje się tak, gdy główne zapytanie jest zapętlone, ponieważ przed rozpoczęciem pętli bieżący post wynosi -1, a po zakończeniu pętli bieżący post jest ponownie resetowany do -1.

Jeśli więc in_the_loop()jest to prawdą, oznacza to, że główny obiekt zapytania zapętla się, co jest potrzebne w tym przypadku (i jest tym samym wynikiem dodawania akcji loop_starti usuwania loop_end, tak jak odpowiedź @ialocin; w rzeczywistości działa z tego samego powodu i dostałem moją +1).

Zaletą podejścia @ ialocin jest to, że chcesz kierować na inny obiekt zapytania niż główny, ponieważ in_the_loop()działa tylko dla zapytania głównego.

gmazzap
źródło
Nie natrafiłem na żadne z wyszukiwań w mojej witrynie ani w Internecie. Ukryty klejnot, który działa. Każde rozwiązanie wykorzystuje is_main_query, naprawdę myślę, że nikt nie przetestował tego dokładnie. Dziękujemy za wkład, bardzo doceniany
Pieter Goosen
1
@PieterGoosen Cieszę się, że to działa. To bardzo stara funkcja, pochodząca z czasów, kiedy is_main_querynie była niczym.
gmazzap
Widzisz, tutaj mnie to przeoczyło, nie jestem starym timerem :-), dołączyłem do Wordpress w 3.3.
Pieter Goosen
2
@GM czy mógłbyś dodać to do swojej odpowiedzi? Jest to przydatna informacja dla innych, którzy mogą natknąć się na tę odpowiedź. Większość ludzi, takich jak ja, nie czyta komentarzy :-)
Pieter Goosen,
1
@PieterGoosen gotowe :)
gmazzap
7

To tylko dodatek do odpowiedzi @ Otto. Żeby było trochę lepiej zrozumiałe. Zasadniczo, co mówi @Otto, musisz odwrócić logikę, co oznacza: jeśli możesz wiarygodnie określić główne zapytanie, możesz dodać - i usunąć - zaczepienie do the_contentfiltra.

Na przykład główne zapytanie może być niezawodnie rozpoznane w pre_get_postsakcji, więc zadziałałoby:

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

Ponieważ powinieneś usunąć filtr, gdy nie jest już potrzebny, myślę, że loop_endakcja powinna być dobrym miejscem do tego i jako jego odpowiednika możemy użyć loop_start. Który wyglądałby tak:

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
źródło
Przetestuje ten jutro. Dziękuję za szczegółowe wyjaśnienie.
Pieter Goosen
Cała przyjemność po mojej stronie jak zawsze @PieterGoosen Nie spiesz się, ale zrób to, bo nie - przynajmniej nie dość.
Nicolai
1
Co się stanie, jeśli w kodzie__kontenera () jest używany kod krótki, a kod ten uruchamia kolejne zapytanie wywołujące metodę_kontener (), zresetuje bieżący obiekt post i pętla będzie kontynuowana? Zastosuje się wszystkie filtry. Dość trudne tutaj, nie zapisane przez dzwonek in_the_loop () ... Właśnie dlatego sugeruję, aby zawsze usuwać unikalne filtry, gdy tylko to zrobią, zgodnie z podejściem @Nicolai
Jonas Lundman
5

Używasz is_main_query()nieprawidłowo. Globalna funkcja is_main_query () zwraca true, chyba że globalna zmienna $ wp_query została ponownie zdefiniowana.

Prawdopodobnie nie ma w 100% wiarygodnego sposobu, aby stwierdzić, z poziomu filtra the_content, czy bieżąca pętla, w której jesteś, jest głównym zapytaniem, czy nie. Filtr treści po prostu filtruje zawartość. Nie ma żadnej zdolności do zrozumienia, do jakiej pętli jest używany.

Zamiast tego należy dodać filtr, gdy jest on potrzebny, a następnie usunąć, gdy nie jest potrzebny.

Otto
źródło
W rzeczywistości jest to rozczarowanie, że nie ma łatwych środków, aby kierować główne zapytanie za pomocą the_contentfiltra
Pieter Goosen
Cóż, to naprawdę nie jest zaskakujące. Jak każdy inny filtr, po prostu filtruje rzeczy. Nie zna kontekstu otaczającego, kiedy jest wywoływany. Może nawet nie zostać wywołany z wnętrza właściwej pętli. Nie ma sposobu, żeby to powiedzieć.
Otto