web-dev-qa-db-fra.com

Des doutes sur le fonctionnement de la requête principale et de la requête personnalisée dans ce thème personnalisé?

Je suis assez nouveau dans le développement de thèmes WordPress et je ne suis pas tellement dans PHP (je viens de Java et C #) et j'ai la situation suivante dans ce thème personnalisé

Comme vous pouvez le voir sur la page d'accueil, je montre d'abord une section (nommée Articoli in evidenza ) contenant les messages en vedette (je l'ai implémentée à l'aide d'une balise spécifique) et sous celle-ci, un autre domaine (nommé Ultimi Articoli ) qui contient le dernier message qui ne figure pas dans le message en vedette.

Pour le faire j'utilise ce code:

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

<?
// 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>

Cela fonctionne bien, mais je doute de la qualité de cette solution et de son fonctionnement.

Pour sélectionner tous les posts en vedette , j'utilise cette ligne qui crée un nouvel objet WP_Query qui définit une requête ayant la balise spécifique featured:

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

Ensuite, j'itère le résultat de cette requête à l'aide de sa méthode have_posts().

Donc, d'après ce que j'ai compris, ceci n'est pas la requête principale de WordPress, mais une nouvelle requête créée par moi. D'après ce que j'ai compris, il est préférable de créer une nouvelle requête (comme c'est le cas) et de ne pas utiliser la requête principale lorsque je souhaite effectuer ce type d'opération.

Est-ce vrai ou est-ce que je manque quelque chose? Si c'est vrai, pouvez-vous m'expliquer pourquoi il est préférable de créer une nouvelle requête personnalisée et de ne pas modifier la requête principale de Wordpress?

Ok, continue. Je montre tous les articles qui n’ont pas la balise sélectionnée. Pour ce faire, j’utilise cet extrait de code qui, au contraire, modifie la requête principale:

    <?
    // 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;
        ?>

Donc, je pense que c'est assez horrible. Est-ce vrai?

Pour faire la même opération, j'ai trouvé cette fonction que j'ai ajoutée à 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' );

Cette fonction a un crochet appelé après la création de l'objet de variable de requête, mais avant l'exécution de la requête.

Donc, d'après ce que j'ai compris, prenons un objet de requête en tant que paramètre d'entrée et le modifie en sélectionnant tous les articles à l'exclusion d'une balise spécifique (dans mon cas, les balises de la variable featured)

Alors, comment puis-je utiliser la requête précédente (celle utilisée pour afficher les messages en vedette) avec cette fonction pour afficher le message non en vedette dans mon thème? Ou dois-je créer une nouvelle requête?

19
AndreaNobili

Votre question est essentiellement de savoir quand exécuter une requête personnalisée et quand utiliser la requête principale. Permet de le décomposer en trois parties

PREMIERE PARTIE

Quand exécuter une requête personnalisée (Ceci n'est pas une liste définitive)

  • Pour créer des curseurs de contenu personnalisés

  • Pour créer une zone de contenu sélectionnée dans une page

  • Sur les modèles page.php si vous devez afficher des publications

  • Si vous avez besoin de contenu personnalisé sur une page d'accueil statique

  • Afficher les articles liés, populaires ou informatifs

  • Tout autre contenu secondaire ou supplémentaire en dehors du champ de la requête principale

Quand utiliser la requête principale.

Pour afficher le contenu principal sur

DEUXIEME PARTIE

Pour sélectionner tous les articles en vedette, j'utilise cette ligne qui crée un nouvel objet WP_Query qui définit une requête ayant la balise spécifique en vedette:

Donc, d'après ce que j'ai compris, il ne s'agit pas de la requête principale de WordPres mais d'une nouvelle requête créée par moi. D'après ce que j'ai compris, il est préférable de créer une nouvelle requête (comme c'est le cas) et de ne pas utiliser la requête principale lorsque je souhaite effectuer ce type d'opération.

Correct. Cela tombe en dehors de la portée de la requête principale. Il s'agit d'un contenu secondaire ou supplémentaire qui ne peut pas être créé avec la requête principale. Vous DEVRIEZ TOUJOURSutiliser soit WP_Query ou get_posts pour créer vos requêtes personnalisées.

NEVER USEquery_posts pour créer des requêtes personnalisées, voire toute autre requête. Mon emphase.

Remarque:Cette fonction n'est pas destinée aux plugins ni aux thèmes. Comme expliqué plus loin, il existe de meilleures options plus performantes pour modifier la requête principale. Query_posts () est une façon trop simpliste et problématique de modifier la requête principale. Il est inefficace (ré-exécute les requêtes SQL) et échouera carrément dans certaines circonstances (particulièrement lorsqu’il s’agit de gérer la pagination des articles).

Passer à autre chose

Ok, je montre tous les articles qui n’ont pas la balise sélectionnée. Pour ce faire, j’utilise cet extrait de code qui, au contraire, modifie la requête principale:

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

Donc, je pense que c'est assez horrible. Est-ce vrai?

Tout cela est faux et votre affirmation est malheureusement vraie. Comme indiqué précédemment, NEVERuse query_posts. Il exécute une nouvelle requête complète, ce qui est mauvais pour les performances et la plupart des cas, il casse la pagination qui fait partie intégrante de la requête principale pour que la pagination fonctionne correctement.

Ceci est votre contenu principal, vous devriez donc utiliser la requête principale avec la boucle par défaut, qui devrait ressembler à ceci, et c'est tout ce dont vous avez besoin

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

Vous pouvez supprimer complètement cette partie, la supprimer, la graver et l’oublier

<?
// 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, une fois que vous avez terminé, vous verrez que les publications de la balise feature apparaissent sur votre page d'accueil à l'aide de la requête principale et de la boucle par défaut.

La bonne façon de supprimer cette balise de la page d'accueil est avec pre_get_posts . Ceci est le moyen approprié de modifier la requête principaleet le crochet que vous devriez toujoursutiliser pour modifier votre boucle de contenu principale.

Donc, le code avec pre_get_posts est correct et c'est la fonction que vous devez utiliser. Juste une chose, vérifiez toujours que vous n’êtes pas sur une page d’administrateur, car pre_get_posts modifie également le back-end. Il s’agit donc du code approprié à utiliser dans functions.php pour supprimer les posts étiquetés en vedette de la page d'accueil.

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

TROISIEME PARTIE

Matériel de lecture supplémentaire qui sera utile à l'avenir

31
Pieter Goosen