Pourquoi devrais-je mettre if (have_posts ()), while tandis que (have_posts ()) ne suffit pas?

22

J'ai une question sur "la boucle".

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

Code extrait de la page du Loop WordPress Codex .

Pourquoi devrais-je mettre une ifpartie? Il semble que s'il y a une whileboucle, ça marche bien.

Dans quel cas le problème se produit s'il n'y a pas de ifdéclaration?

modifier

J'ai accepté la réponse de @ Chip. mais honnêtement, je n'ai besoin que de la dernière partie.

Je sais maintenant ce que je voulais savoir de ma question.

ifn'est nécessaire que si vous souhaitez mettre un en-tête ou un pied de page qui ne doit être écrit qu'une seule fois. si vous n'utilisez pas le "wrapper", alors l' ifinstruction n'est pas nécessaire.

fer à repasser
la source
2
J'ai voté avant de lire le_contenu, le_titre est déterminant!
brasofilo
Excellent (final) montage. La plupart des gens utilisent les if et while directement l'un après l'autre sans jamais utiliser d'autre. Probablement à cause du copier-coller.
Herbert Van-Vliet

Réponses:

29

Le chargeur de modèles WordPress inclura le fichier de modèle contextuel approprié dans de nombreuses circonstances, même si la requête pour ce contexte ne renvoie aucun message. Par exemple:

  • Index des principaux articles du blog
  • Index des archives de catégorie (la catégorie existe, mais n'a pas de messages)
  • Index d'archivage des balises (la balise existe, mais n'a pas de publication)
  • Index des archives des auteurs (l'auteur existe, mais n'a aucun message)
  • Index des résultats de recherche

Ainsi, dans ces cas, le fichier de modèle approprié sera chargé, mais aucune publication ne sera générée, car la requête ne renvoie aucune publication.

Exemples de validation de principe:

Ainsi, dans ces contextes, il est utile que le fichier modèle inclue le if ( have_posts() )conditionnel.

Dans d'autres contextes, le fichier de modèle ne sera jamais chargé si la requête ne renvoie aucune publication. Par exemple:

  • Article de blog unique
  • Page statique

Dans ces contextes, if ( have_posts() )est probablement inutile.

modifier

Je comprends que la requête est invoquée par the_post (), non? Et si while (have_posts ()) existe, la requête ne se produit jamais s'il n'y a pas de publication.

Pour comprendre ce qui se passe, vous devez regarder l'ordre des actions WordPress . Commençant par wp_loaded(et en omettant certains pour plus de clarté):

  • wp_loaded
  • parse_request
  • send_headers
  • parse_query
  • pre_get_posts
  • wp
  • template_redirect
  • get_header
  • wp_head
  • the_post
  • wp_footer

Alors, que se passe-t-il et dans quel ordre?

  • La requête est invoquée:
    • parse_query
    • pre_get_posts
    • wp
  • Le modèle est sélectionné:
    • template_redirect
  • Le modèle est chargé / sorti. Les actions suivantes sont déclenchées par le modèle :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Ainsi, the_postdéclenché par the_post(), se produit longtemps après l'analyse de la requête, la récupération des publications et le chargement du modèle.

Je suis très reconnaissant que vous donniez beaucoup d'informations que je ne connaissais pas, mais ce n'est pas ce que j'ai demandé.

Oh, mais je crois que c'est exactement ce que vous avez demandé.

La vraie question est: qu'est-ce qu'un retour de requête valide ? Pour des contextes tels que l'index d'archive de catégorie, la requête est valide et le modèle de catégorie est chargé, si l'ID de catégorie interrogé existe, même si aucune publication n'est affectée à cette catégorie .

Pourquoi? Parce que la requête en cours d'analyse est (IIRC) &cat={ID}- qui est une requête valide même s'il n'y a pas de messages affectés à cette catégorie , et n'entraîne donc pas de 404 lors de l'analyse.

Dans ce cas, vous obtenez une requête valide et un fichier de modèle chargé, mais pas de publications . Ainsi if ( have_posts() ), est, en fait pertinent. Encore une fois, voici un exemple: la catégorie existe, mais aucun poste n'est affecté. Le fichier de modèle de catégorie est chargé, avec if ( have_posts() )retourfalse .

Cela ne sera pas vrai pour les requêtes qui incluent une variable de publication ( &p={ID}) telles que les publications de blog uniques et les pages statiques, car la publication n'existe pas réellement et lorsqu'elle est analysée, la requête ne renvoie pas d'objet valide.

Modifier 2

Si je comprends à juste titre s'il n'y a pas de if (have_posts ()) dans un modèle de catégorie et que la catégorie n'a pas de publication, alors il renvoie 404.php, même s'il doit renvoyer category-sample.php sans publication. Est-ce correct?

N'oubliez pas: le modèle est sélectionné à template_redirect. Donc, si la requête est valide, le fichier de modèle approprié est chargé. Si la requête n'est pas valide, le modèle 404 est chargé.

Ainsi, une fois qu'un modèle est chargé - par exemple le modèle de catégorie - une fois la boucle sortie, le modèle ne change pas .

Regardez à nouveau l'ordre des actions:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- le modèle est choisi et chargé ici. Il s'agit du modèle de point de non-retour . Le modèle ne peut pas changer après ce point.
  • ...
  • the_post- postdata est configuré ici, dans le cadre de l'appel de boucle. Ceci est appelé à l'intérieur du modèle et le modèle ne change pas en fonction des données disponibles dans l'objet de requête

Édition finale

Et je prétends que tout en vérifiant l'existence de messages, pourquoi devrais-je exécuter le même test deux fois. C'est ma question du premier point que je ne posais qu'à ce sujet.

Et avec cela, je comprends enfin: tout au long, votre question n'a rien à voir avec WordPress , ou la boucle WordPress . Vous demandez comment encapsuler une whileboucle PHP arbitraire dans une ifcondition qui vérifie la même condition.

Cette question sort du cadre du WPSE, mais je vais expliquer brièvement:

Un ifconditionnel est une évaluation binaire: c'est soit trueou false, et ce qui se passe à l' intérieur de ce conditionnel est exécuté une fois .

Un whileconditionnel est une boucle : il reste vrai pour une période discrète, basé sur une sorte de compteur; et ce qui se passe à l' intérieur de ce conditionnel est exécuté plusieurs fois - une fois pour chaque itération du compteur.

Supposons donc que vous souhaitiez générer une liste de choses non ordonnée, si la liste de choses est remplie. Si vous utilisez une whileboucle et omettez l' ifencapsuleur, votre balisage ressemblera à ceci:

<ul>
<?php while ( list_of_things() ) : ?>
    <li><?php the_list_item(); ?></li>
<?php endwhile; ?>
</ul>

Et s'il list_of_things()était vide, la sortie rendue serait:

<ul>
</ul>

Ce qui laisse un balisage inutile (et invalide).

Mais si vous ajoutez un ifwrapper conditionnel, vous pouvez le faire:

<?php if ( list_of_things() ) : ?>
    <ul>
    <?php while ( list_of_things() ) : ?>
        <li><?php the_list_item(); ?></li>
    <?php endwhile; ?>
    </ul>
<?php endif; ?>

Et s'il list_of_things()était vide, aucun balisage ne serait généré.

Ce n'est qu'un exemple. Il existe de nombreuses utilisations pour ce ifwrapper conditionnel, et le ifwrapper conditionnel sert un objectif entièrement différent de la whileboucle.

Chip Bennett
la source
2
Dans mes modèles de poste / page singuliers, depuis longtemps, j'utilise uniquement the_post();parce que le whilen'est pas nécessaire non plus. +1 pour l'exhaustivité des informations.
gmazzap
@GM La suppression éventuelle de la if( have_posts() )déclaration est logique (c'est ce que j'essaie de découvrir), mais ne l'utilisez pas uniquement the_post()dans des pages singulières!
Sunyatasattva
@ChipBennett Tout bien considéré, pensez - vous qu'il est sûr d'enlever l' if( have_post() )état avant la boucle complète dans le contexte single-*.phpet les page-*.phpfichiers de modèle?
Sunyatasattva
1
«Sûr» n'a vraiment aucun sens définitif dans ce contexte.
Chip Bennett du
10

Il est vraiment impossible d'améliorer la réponse de Chip, mais juste pour aller droit au but:

Utilisez la ifpartie si vous souhaitez que quelque chose de différent s'affiche lorsqu'il n'y a pas de messages . Cela est particulièrement utile, par exemple, sur une page d'archive de date ou de catégorie. Si quelqu'un accède à une page qui n'a pas de messages, c'est bien d'avoir un message qui le dit, plutôt que rien ne s'affiche du tout, car la boucle n'est jamais exécutée.

if ( have_posts() ):
  // Yep, we have posts, so let's loop through them.
  while ( have_posts() ) : the_post();
  // do your loop
  endwhile;
else :
  // No, we don't have any posts, so maybe we display a nice message
  echo "<p class='no-posts'>" . __( "Sorry, there are no posts at this time." ) . "</p>";
endif;
Tom Auger
la source
Et c'est tout ce qu'il faut savoir.
Herbert Van-Vliet
0

Il peut y avoir certaines considérations qui ne sont pas incluses dans les réponses jusqu'à présent. Il n'est pas recommandé d'omettre l'instruction if.

L'instruction if est couramment utilisée pour:

  • afficher quelque chose comme no posts foundpour indiquer que la catégorie en question n'a pas d'articles affectés.
  • pour décider si le html environnant (comme un ul) doit être affiché avant et après les articles.

Et si un nouveau crochet est ajouté?

Un autre problème possible de ne pas utiliser l'instruction if est que si l'équipe wordpress décidait jamais d'ajouter un nouveau hook qui se déclenche au premier $wp_query->have_posts()appel, il se déclencherait au mauvais moment. Et si cela provoque un comportement inattendu, ce serait votre faute si vous ne suivez pas correctement les spécifications.

D'autres développeurs s'attendent à voir une structure spécifique pour la boucle wordpress

Je suppose que d'autres développeurs s'attendent à voir l'intégralité de la boucle wordpress. Alors peut-être que c'est une mauvaise idée de les faire chercher une instruction if qui n'est pas là.

RMo
la source
-1

Je vois cela comme une question fondamentale de la théorie de la structure de contrôle. Le bloc inclus dans la boucle while ne s'exécute pas une seule fois si la condition (have_posts ()) est évaluée comme fausse la première fois.

Ainsi, le but de if ( have_posts() )dans la boucle WordPress est d'exécuter la fonction has_posts () une seule fois avant l'évaluation de la condition while. Si cela have_posts()n'a pas d'effets secondaires, alors if ( have_posts() )c'est totalement inutile. Si have_posts()cela a des effets secondaires, vous pouvez simplifier comme suit:

<?php have_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
Schparky
la source
3
Cette simplification n'est pas PHP valide, vous avez une instruction else qui n'a pas d'instructions if attachées. Au mieux, c'est difficile à lire
Tom J Nowell
1
Le ifest là à cause de l' elseaprès. Aucune autre raison. S'il n'y a pas de messages, il est préférable d'afficher un joli message "pas de messages" plutôt que de ne rien afficher.
Otto