De ce ar trebui să folosesc if(have_posts()), nu este while(have_posts()) suficient?

9 oct. 2013, 11:32:22
Vizualizări: 51.2K
Voturi: 26

Am o întrebare despre "the loop".

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Ne pare rău, niciun articol nu corespunde criteriilor.'); ?></p>
<?php endif; ?>

Cod preluat din pagina WordPress Codex despre The Loop.

De ce ar trebui să pun partea cu if? Se pare că dacă există bucla while, funcționează bine.

În ce situație apar probleme dacă nu există declarația if?

Editare

Am acceptat răspunsul lui @Chip, dar sincer vorbind, am avut nevoie doar de ultima parte.

Acum știu ce voiam să aflu din întrebarea mea.

Declarația if este necesară doar când vrei să pui un antet sau subsol care ar trebui scris o singură dată. Dacă nu folosești această "învelitoare", atunci declarația if nu este necesară.

2
Comentarii

Am votat înainte de a citi the_content, the_title este decisiv!

brasofilo brasofilo
9 oct. 2013 13:36:51

Editare excelentă (finală). Majoritatea oamenilor folosesc if și while direct unul după altul fără a folosi vreodată un else. Probabil din cauza copy & paste.

Herbert Van-Vliet Herbert Van-Vliet
5 mar. 2018 04:59:10
Toate răspunsurile la întrebare 4
4
33

Încărcătorul de șabloane WordPress va include fișierul de șablon contextual corespunzător în multe circumstanțe, chiar dacă interogarea pentru acel context nu returnează nicio postare. De exemplu:

  • Indexul principal al postărilor de blog
  • Indexul arhivei de categorii (Categoria există, dar nu are postări)
  • Indexul arhivei de etichete (Eticheta există, dar nu are postări)
  • Indexul arhivei de autori (Autorul există, dar nu are postări)
  • Rezultatele căutării

Astfel, în aceste cazuri, fișierul de șablon corespunzător va fi încărcat, dar nicio postare nu va fi afișată, deoarece interogarea nu returnează postări.

Exemple de concept:

Deci, în aceste contexte, este util ca fișierul de șablon să includă condiționalul if ( have_posts() ).

În alte contexte, fișierul de șablon nu va fi niciodată încărcat dacă interogarea nu returnează postări. De exemplu:

  • Postare individuală de blog
  • Pagină statică

În aceste contexte, if ( have_posts() ) este probabil inutil.

Editare

Am înțeles că interogarea este invocată de the_post(), corect? Și dacă while(have_posts()) există, interogarea nu are loc niciodată dacă nu există postări.

Pentru a înțelege ce se întâmplă, trebuie să te uiți la ordinea acțiunilor WordPress. Începând cu wp_loaded (și omitând unele pentru claritate):

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

Deci, ce se întâmplă și în ce ordine?

  • Interogarea este invocată:
    • parse_query
    • pre_get_posts
    • wp
  • Șablonul este selectat:
    • template_redirect
  • Șablonul este încărcat/afișat. Următoarele acțiuni sunt declanșate de șablon:
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Deci, the_post, declanșat de the_post(), are loc mult după ce interogarea este analizată, postările sunt preluate și șablonul este încărcat.

Sunt foarte recunoscător că oferi o mulțime de informații pe care nu le știam, dar nu asta am întrebat.

Oh, dar cred că este exact ceea ce ai întrebat.

Întrebarea reală este: ce este un rezultat valid al interogării? Pentru contexte precum indexul arhivei de categorii, interogarea este validă, iar șablonul de categorie este încărcat, dacă ID-ul categoriei interogate există, chiar dacă nu există postări atribuite acelei categorii.

De ce? Pentru că interogarea analizată este (dacă îmi amintesc corect) &cat={ID} - care este o interogare validă chiar dacă nu există postări atribuite acelei categorii și, prin urmare, nu duce la o eroare 404 la analiză.

În acest caz, obții o interogare validă și un fișier de șablon încărcat, dar nicio postare. Astfel, if ( have_posts() ), este, de fapt, relevant. Din nou, iată un exemplu: categoria există, dar nu are postări atribuite. Fișierul șablon de categorie este încărcat, cu if ( have_posts() ) returnând false.

Acest lucru nu va fi valabil pentru interogările care includ o variabilă de postare (&p={ID}), cum ar fi postările individuale de blog și paginile statice, deoarece postarea nu va exista de fapt, iar la analiză, interogarea nu va returna un obiect valid.

Editare 2

Dacă înțeleg corect, dacă nu există if(have_posts()) într-un șablon de categorie și categoria nu are postări, atunci returnează 404.php, chiar dacă ar trebui să returneze category-sample.php fără postări. Este corect?

Nu. Amintește-ți: șablonul este selectat la template_redirect. Deci, dacă interogarea este validă, atunci fișierul de șablon corespunzător este încărcat. Dacă interogarea nu este validă, atunci șablonul 404 este încărcat.

Deci, odată ce un șablon este încărcat - de exemplu, șablonul de categorie - odată ce bucla este afișată, șablonul nu se schimbă.

Uită-te din nou la ordinea acțiunilor:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect - șablonul este ales și încărcat aici. Acesta este punctul de neîntoarcere al șablonului. Șablonul nu se poate schimba după acest punct.
  • ...
  • the_post - datele postării sunt configurate aici, ca parte a apelului buclei. Acesta este apelat în interiorul șablonului, iar șablonul nu se schimbă în funcție de datele disponibile în obiectul de interogare

Editare finală

Și susțin că while verifică existența postărilor, de ce ar trebui să rulez același test de două ori. Aceasta este întrebarea mea din primul punct pe care am tot întrebat-o doar despre asta.

Și cu asta, înțeleg în sfârșit: de la bun început, întrebarea ta nu avea nicio legătură cu WordPress sau cu Bucla WordPress. Întrebi despre înfășurarea oricărei bucle PHP arbitrare while într-un condițional if care verifică aceeași condiție.

Această întrebare este în afara domeniului WPSE, dar voi explica pe scurt:

Un condițional if este o evaluare binară: este fie true, fie false, iar ceea ce se întâmplă în interiorul acelui condițional este executat o singură dată.

Un condițional while este o buclă: rămâne adevărat pentru o anumită perioadă discretă, bazată pe un fel de contor; iar ceea ce se întâmplă în interiorul acelui condițional este executat de mai multe ori - o dată pentru fiecare iterație a contorului.

Deci, să presupunem că vrei să afișezi o listă neordonată de lucruri, dacă lista de lucruri este populată. Dacă folosești o buclă while și omiți înfășurătoarea if, marcajul tău ar arăta astfel:

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

Și dacă list_of_things() ar fi gol, rezultatul afișat ar fi:

<ul>
</ul>

Ceea ce lasă marcaje inutile (și invalide).

Dar dacă adaugi un condițional if de înfășurare, poți face asta:

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

Și dacă list_of_things() ar fi gol, niciun marcaj nu ar fi afișat.

Acesta este doar un exemplu. Există multe utilizări pentru acea înfășurătoare condițională if, iar înfășurătoarea condițională if are un scop complet diferit față de bucla while.

9 oct. 2013 17:02:05
Comentarii

În șabloanele mele pentru postări/pagini individuale, de mult timp, folosesc doar the_post(); deoarece și while este inutil. +1 pentru completitudinea informațiilor.

gmazzap gmazzap
9 oct. 2013 20:00:59

@G.M. Posibil ca eliminarea instrucțiunii if( have_posts() ) să aibă sens (asta încerc să aflu), dar nu folosi doar the_post() în paginile individuale!

Sunyatasattva Sunyatasattva
12 oct. 2013 23:53:37

@ChipBennett Luând în considerare toate aspectele, crezi că este sigur să elimini condiția if( have_post() ) înaintea buclei complete în contextul fișierelor de șablon single-*.php și page-*.php?

Sunyatasattva Sunyatasattva
12 oct. 2013 23:55:00

"Sigur" nu are cu adevărat o semnificație definitivă în acest context.

Chip Bennett Chip Bennett
13 oct. 2013 00:05:38
1
11

Este cu adevărat imposibil să îmbunătățim răspunsul lui Chip, dar pentru a ajunge direct la subiect:

Folosește partea cu if dacă dorești să afișezi ceva diferit atunci când nu există articole. Acest lucru este util în special, de exemplu, pe o pagină de arhivă după dată sau categorie. Dacă cineva navighează la o pagină care nu conține articole, este bine să afișezi un mesaj care să indice acest lucru, în loc să nu apară nimic, deoarece bucla nu se execută deloc.

if ( have_posts() ):
  // Da, avem articole, așa că să le parcurgem.
  while ( have_posts() ) : the_post();
  // execută bucla ta
  endwhile;
else :
  // Nu, nu avem articole, așa că poate afișăm un mesaj frumos
  echo "<p class='no-posts'>" . __( "Ne pare rău, momentan nu există articole." ) . "</p>";
endif;
16 oct. 2013 04:18:26
Comentarii

Și acestea sunt toate lucrurile pe care trebuie să le știi.

Herbert Van-Vliet Herbert Van-Vliet
19 mai 2018 00:08:22
0

Pot exista câteva considerații care nu sunt incluse în răspunsurile de până acum. Nu este recomandat să omiți instrucțiunea if.

Instrucțiunea if este folosită în mod obișnuit pentru:

  • a afișa ceva de genul nu au fost găsite articole pentru a indica faptul că categoria respectivă nu are articole atribuite.
  • a decide dacă codul HTML înconjurător (cum ar fi un ul) ar trebui să fie afișat înainte și după articole.

Ce se întâmplă dacă este adăugat un nou hook?

O altă problemă posibilă a neutilizării instrucțiunii if este că, dacă echipa WordPress ar decide vreodată să adauge un nou hook care să se declanșeze la primul apel $wp_query->have_posts(), acesta s-ar declanșa la momentul nepotrivit. Și dacă acest lucru provoacă comportamente neașteptate, ar fi vina ta pentru că nu ai urmat specificațiile corect.

Alți dezvoltatori se așteaptă să vadă o structură specifică pentru bucla WordPress

Presupun că alți dezvoltatori se așteaptă să vadă întreaga buclă WordPress. Așadar, poate că este o idee proastă să-i faci să caute o instrucțiune if care nu există.

28 nov. 2019 13:24:39
2
-1

Consider aceasta o întrebare fundamentală din teoria structurilor de control. Blocul închis în interiorul buclei while nu se execută niciodată dacă condiția (have_posts()) este evaluată ca falsă din prima.

Prin urmare, scopul lui if ( have_posts() ) în bucla WordPress este doar de a executa funcția have_posts() o singură dată înainte de evaluarea condiției while. Dacă have_posts() nu are efecte secundare, atunci if ( have_posts() ) este complet inutil. Dacă have_posts() are efecte secundare, puteți simplifica astfel:

<?php have_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Ne pare rău, nicio postare nu corespunde criteriilor tale.'); ?></p>
<?php endif; ?>
24 oct. 2014 01:59:17
Comentarii

Această simplificare este PHP invalid, ai o instrucțiune else care nu este atașată la nicio instrucțiune if. Cel mult, este greu de citit

Tom J Nowell Tom J Nowell
24 oct. 2014 02:27:59

if-ul este acolo din cauza else-ului care urmează. Niciun alt motiv. Dacă nu există postări, atunci afișarea unui mesaj frumos "nici o postare" este mai bună decât afișarea nimic.

Otto Otto
24 oct. 2014 03:13:09