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

20

Je suis assez nouveau dans le développement de thèmes WordPress et je ne suis pas tellement en 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 articles en vedette (je l'ai implémentée en utilisant une balise spécifique) et en dessous il y a une autre zone (nommée Ultimi Articoli ) qui contient le dernier article qui ne sont pas le poste en vedette.

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

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

Cela fonctionne bien, mais j'ai quelques doutes sur la qualité de cette solution et sur son fonctionnement exact.

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

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

Ensuite, j'itère sur ce résultat de requête en utilisant sa have_posts()méthode.

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

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

Ok, continue. Je montre tous les messages qui n'ont pas la balise «en vedette». Pour ce faire, j'utilise cet extrait de code, qui au contraire modifie la requête principale:

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

Je pense donc que c'est assez horrible. Est-ce vrai?

MISE À JOUR:

Pour faire la même opération, j'ai trouvé cette fonction (dans la grande réponse ci-dessous) 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 possède un hook qui est appelé après la création de l'objet variable de requête, mais avant l'exécution de la requête réelle.

Donc, d'après ce que j'ai compris, il prend un objet de requête comme paramètre d'entrée et le modifie (en fait le filtre) en sélectionnant tous les messages à l'exclusion d'une balise spécifique (dans mon cas, les featuredmessages de balise)

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

AndreaNobili
la source

Réponses:

33

Votre véritable 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

PARTIE UN

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

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

  • Pour créer une zone de contenu en vedette dans une page

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

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

  • Afficher des articles connexes, populaires ou informatifs

  • Tout autre contenu secondaire ou supplémentaire hors de la portée de la requête principale

Quand utiliser la requête principale.

Pour afficher le contenu principal sur

DEUXIÈME 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, ce n'est pas la requête principale de WordPres mais c'est 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 cela est fait) et de ne pas utiliser la requête principale lorsque je souhaite effectuer ce type d'opérations

Correct. Cela tombe hors de portée pour 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 DEVEZ TOUJOURS utiliser soit WP_Queryou get_postspour créer vos requêtes personnalisées.

NE JAMAIS UTILISER query_posts pour créer des requêtes personnalisées, ou même toute autre requête. Mon accent.

Remarque: Cette fonction n'est pas destinée à être utilisée par des plugins ou des thèmes. Comme expliqué plus loin, il existe des options meilleures et plus performantes pour modifier la requête principale. query_posts () est un moyen trop simpliste et problématique de modifier la requête principale d'une page en la remplaçant par une nouvelle instance de la requête. Il est inefficace (réexécute les requêtes SQL) et échouera carrément dans certaines circonstances (en particulier souvent lors de la pagination des publications).

Aller de l'avant

Ok, en cours je montre tous les articles qui n'ont pas la balise en vedette, 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 )));

Je pense donc que c'est assez horrible. Est-ce vrai?

Tout cela est faux et votre déclaration est malheureusement vraie. Comme dit précédemment, ne l' utilisez JAMAISquery_posts . Il exécute une nouvelle requête complète, ce qui est mauvais pour les performances, et il casse la plupart des cas, ce qui fait partie intégrante de la requête principale pour que la pagination fonctionne correctement.

Ceci est votre contenu principal, vous devez 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 vous débarrasser complètement de 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 fait cela, vous verrez que les publications de la balise de fonctionnalité apparaissent dans votre page d'accueil en utilisant la requête principale et la boucle par défaut.

La bonne façon de supprimer cette balise de la page d'accueil est d'utiliser pre_get_posts. C'est la bonne façon de modifier la requête principale et le hook que vous devez toujours utiliser pour apporter des modifications à votre boucle de contenu principale.

Ainsi, le code avec pre_get_postsest 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'administration car cela pre_get_postsmodifie également le back-end. C'est donc le code propre à une utilisation dans functions.phpdes postes de remove Marqué avec fonctionnalités 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] );
    }
}

PARTIE TROIS

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

Pieter Goosen
la source
Mon plaisir. Content que vous ayez trouvé ça utile. Enjou :-)
Pieter Goosen
Wow, toute une réponse! Il me manque cependant une information critique: comment dire à WP "c'est une page de messages" en plus de la page de messages principale? Disons que je veux une liste de messages avec les catégories 10,11,12 et une autre liste avec les catégories 13,14,15. Je vois comment je pourrais utiliser pre_get_posts pour injecter les catégories dans la requête principale, mais comment puis-je dire à WP de rendre cela comme une liste de messages avec une pagination appropriée? Dois-je vraiment suivre votre réponse détaillée ici wordpress.stackexchange.com/a/215027/74134 car c'est une page? Certes, WordPress permet nativement plusieurs listes de blogs dans un site?
Mark Berry