Masz wątpliwości dotyczące sposobu działania zapytania głównego i zapytania niestandardowego w tym niestandardowym motywie?

20

Jestem całkiem nowy w tworzeniu motywów WordPress i nie przepadam za PHP (pochodzę z Java i C #) i mam następującą sytuację w tym niestandardowym motywie

Jak widać na stronie głównej, najpierw pokazuję sekcję (o nazwie Articoli in evidenza ) zawierającą polecane posty (zaimplementowałem ją za pomocą określonego tagu), a pod nią jest inny obszar (o nazwie Ultimi Articoli ), który zawiera najnowszy post które nie są polecanym postem.

Aby to zrobić, używam tego kodu:

<section id="blog-posts">

<header class="header-sezione">
        <h2>Articoli in evidenza</h2>
</header>

<!--<?php query_posts('tag=featured');?>-->

<?php
    $featured = new WP_Query('tag=featured');

    if ($featured->have_posts()) : 
            while ($featured->have_posts()) : $featured->the_post();
            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
                 get_template_part('content', get_post_format());

             endwhile;
        wp_reset_postdata();
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>


<header class="header-sezione">
    <h2>Ultimi Articoli</h2>
</header>

<?php
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>

</section>

Działa dobrze, ale mam wątpliwości co do jakości tego rozwiązania i jego dokładnego działania.

Aby wybrać wszystkie polecane posty , używam tego wiersza, który tworzy nowy WP_Queryobiekt, który definiuje zapytanie posiadające określony znacznik featured:

$featured = new WP_Query('tag=featured');

Następnie iteruję wynik tego zapytania, używając jego have_posts()metody.

Z tego, co rozumiem, nie jest to główne zapytanie WordPress, ale nowe zapytanie utworzone przeze mnie. Z tego, co rozumiem, lepiej utworzyć nowe zapytanie (tak jak zostało wykonane) i nie używać głównego zapytania, gdy chcę wykonać tego rodzaju operację.

Czy to prawda, czy coś mi brakuje? Jeśli to prawda, czy możesz mi wyjaśnić, dlaczego lepiej jest utworzyć nowe niestandardowe zapytanie, a nie modyfikować głównego zapytania Wordpress?

Okej, idziemy dalej. Pokazuję wszystkie posty, które nie mają tagu „polecany”. Aby to zrobić, używam tego fragmentu kodu, który przeciwnie, modyfikuje główne zapytanie:

    <?php
    // get the term using the slug and the tag taxonomy
    $term = get_term_by( 'slug', 'featured', 'post_tag' );
    // pass the term_id to tag__not_in
    query_posts( array( 'tag__not_in' => array ( $term->term_id )));
    ?>

    <?php
        if (have_posts()) :
            // Start the Loop.
            while (have_posts()) : the_post();
                get_template_part('content', get_post_format());

            endwhile;
        else :
            // If no content, include the "No posts found" template.
            get_template_part('content', 'none');

        endif;
        ?>

Myślę więc, że to jest okropne. Czy to prawda?

AKTUALIZACJA:

Aby wykonać tę samą operację, znalazłem tę funkcję (w świetnej odpowiedzi poniżej), którą dodałem do functions.php

function exclude_featured_tag( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'tag__not_in', 'array(ID OF THE FEATURED TAG)' );
    }
}
add_action( 'pre_get_posts', 'exclude_featured_tag' );

Ta funkcja ma zaczep, który jest wywoływany po utworzeniu obiektu zmiennej zapytania, ale przed uruchomieniem rzeczywistego zapytania.

Tak więc, z tego co zrozumiałem, pobiera obiekt zapytania jako parametr wejściowy i modyfikuje go (faktycznie filtruje), wybierając wszystkie posty z wyłączeniem określonego znacznika (w moim przypadku featuredposty znaczników)

Jak więc użyć poprzedniej kwerendy (tej używanej do wyświetlania polecanych postów) z tą funkcją, aby wyświetlać tylko nie polecane posty w moim motywie? Czy muszę utworzyć nowe zapytanie?

AndreaNobili
źródło

Odpowiedzi:

33

Rzeczywiste pytanie dotyczy w zasadzie, kiedy uruchomić zapytanie niestandardowe, a kiedy skorzystać z zapytania głównego. Podzielmy to na trzy części

CZĘŚĆ PIERWSZA

Kiedy uruchomić niestandardowe zapytanie (To nie jest ostateczna lista)

  • Aby utworzyć niestandardowe suwaki treści

  • Aby utworzyć wyróżniony obszar zawartości na stronie

  • Szablony page.php, jeśli chcesz wyświetlać posty

  • Jeśli potrzebujesz niestandardowej treści na statycznej stronie głównej

  • Wyświetlaj powiązane, popularne lub informacyjne posty

  • Wszelkie inne treści wtórne lub uzupełniające poza zakresem zapytania głównego

Kiedy skorzystać z głównego zapytania.

Aby wyświetlić podstawową zawartość

CZĘŚĆ DRUGA

Aby wybrać wszystkie polecane posty, korzystam z tego wiersza, który tworzy nowy obiekt WP_Query, który definiuje zapytanie z określonym znacznikiem:

Z tego, co rozumiem, nie jest to główne zapytanie WordPres, ale jest to nowe zapytanie utworzone przeze mnie. Z tego, co rozumiem, lepiej jest utworzyć nowe zapytanie (tak jak zostało wykonane) i nie używać zapytania głównego, gdy chcę wykonać tego rodzaju operacje

Poprawny. Nie mieści się to w głównym zapytaniu. Jest to treść wtórna lub uzupełniająca, której nie można utworzyć za pomocą głównego zapytania. Ty zawsze powinien zastosować jedną WP_Querylub get_postsstworzyć swoje własne pytania.

NIGDY NIE UŻYWAJ query_posts do tworzenia niestandardowych zapytań ani nawet innych zapytań. Mój nacisk.

Uwaga: Ta funkcja nie jest przeznaczona do używania przez wtyczki lub motywy. Jak wyjaśniono później, istnieją lepsze, bardziej wydajne opcje zmiany głównego zapytania. query_posts () to zbyt uproszczony i problematyczny sposób modyfikowania głównego zapytania strony poprzez zastąpienie go nowym wystąpieniem zapytania. Jest nieefektywny (ponownie uruchamia zapytania SQL) i w niektórych okolicznościach po prostu zawiedzie (szczególnie często w przypadku stronicowania postów).

Iść dalej

Ok, dalej pokazuję wszystkie posty, które nie mają opisanego tagu, w tym celu używam tego fragmentu kodu, który wręcz przeciwnie modyfikuje główne zapytanie:

query_posts( array( 'tag__not_in' => array ( $term->term_id )));

Myślę więc, że to jest okropne. Czy to prawda?

To wszystko źle, a twoje stwierdzenie jest niestety prawdziwe. Jak powiedziano wcześniej, NIGDY nie używaj query_posts. Uruchamia całkowicie nowe zapytanie, które jest niekorzystne z punktu widzenia wydajności, i w większości przypadków psuje paginację, która jest integralną częścią głównego zapytania, aby paginacja działała poprawnie.

To jest twoja podstawowa treść, więc powinieneś używać głównego zapytania z domyślną pętlą, która powinna wyglądać tak i to wszystko, czego potrzebujesz

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
?>

Możesz całkowicie pozbyć się tej części, usunąć ją, spalić i zapomnieć o niej

<?
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

OK, gdy to zrobisz, zobaczysz, że posty z tagu funkcji pojawiają się na stronie głównej za pomocą głównego zapytania i domyślnej pętli.

Prawidłowy sposób usunięcia tego tagu ze strony głównej to pre_get_posts. Jest to właściwy sposób na zmianę głównego zapytania i zaczepu, którego należy zawsze używać do wprowadzania zmian w głównej pętli treści.

Tak więc kod z pre_get_postsjest poprawny i jest to funkcja, której powinieneś użyć. Tylko jedna rzecz, zawsze sprawdzaj, czy nie jesteś na stronie administratora, ponieważ pre_get_postszmienia również zaplecze. Jest to więc odpowiedni kod functions.phpdo usuwania postów oznaczonych jako polecane ze strony głównej

add_action( 'pre_get_posts', 'exclude_featured_tag' );
function exclude_featured_tag( $query ) 
{
    if (    !is_admin() 
         && $query->is_home() 
         && $query->is_main_query() 
    ) {
        $query->set( 'tag__not_in', [ID OF THE FEATURED TAG] );
    }
}

CZĘŚĆ TRZECIA

Dodatkowe materiały do ​​czytania, które będą pomocne w przyszłości

Pieter Goosen
źródło
Cała przyjemność po mojej stronie. Cieszę się, że uznałeś to za przydatne. Enjou :-)
Pieter Goosen
Wow, niezła odpowiedź! Brakuje mi jednak jednej ważnej informacji: jak powiedzieć WP „to jest strona postów” oprócz głównej strony postów? Powiedzmy, że chcę jedną listę postów z kategoriami 10,11,12, a drugą listę z kategoriami 13,14,15. Rozumiem, jak mógłbym użyć pre_get_posts do wstrzyknięcia kategorii do głównego zapytania, ale w jaki sposób mogę powiedzieć WP, aby renderowało to jako listę postów z odpowiednim podziałem na strony? Czy naprawdę muszę śledzić twoją obszerną odpowiedź tutaj wordpress.stackexchange.com/a/215027/74134, ponieważ jest to strona? Z pewnością WordPress natywnie pozwala na wiele list blogów w witrynie?
Mark Berry,