Perché dovrei usare if(have_posts()), non è sufficiente while(have_posts())?

9 ott 2013, 11:32:22
Visualizzazioni: 51.2K
Voti: 26

Ho una domanda riguardo "the loop".

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Spiacenti, nessun articolo corrisponde ai tuoi criteri.'); ?></p>
<?php endif; ?>

Codice preso dalla pagina del Codex WordPress sul Loop.

Perché dovrei inserire la parte con if? Sembra che se c'è il ciclo while, funzioni bene.

In quale caso si verifica un problema se non c'è l'istruzione if?

Modifica

Ho accettato la risposta di @Chip, ma onestamente mi serviva solo l'ultima parte.

Ora ho capito quello che volevo sapere dalla mia domanda.

L'istruzione if serve solo quando necessario, se vuoi inserire un'intestazione o un piè di pagina che deve essere scritto una sola volta. Se non usi il "wrapper", allora l'istruzione if non è necessaria.

2
Commenti

Ho votato prima di leggere il_content, the_title è decisivo!

brasofilo brasofilo
9 ott 2013 13:36:51

Modifica (finale) eccellente. Molte persone usano if e while direttamente uno dopo l'altro senza mai usare un else. Probabilmente a causa del copia & incolla.

Herbert Van-Vliet Herbert Van-Vliet
5 mar 2018 04:59:10
Tutte le risposte alla domanda 4
4
33

Il caricatore di template di WordPress includerà il file template contestuale appropriato in molte circostanze, anche se la query per quel contesto non restituisce alcun post. Ad esempio:

  • L'indice principale dei post del blog
  • L'indice dell'archivio di categoria (la categoria esiste, ma non ha post)
  • L'indice dell'archivio di tag (il tag esiste, ma non ha post)
  • L'indice dell'archivio dell'autore (l'autore esiste, ma non ha post)
  • I risultati della ricerca

Pertanto, in questi casi, verrà caricato il file template appropriato, ma non verranno visualizzati post perché la query non ne restituisce.

Esempi dimostrativi:

Quindi, in questi contesti, è utile che il file template includa il condizionale if ( have_posts() ).

In altri contesti, il file template non verrà mai caricato se la query non restituisce post. Ad esempio:

  • Singolo post del blog
  • Pagina statica

In questi contesti, if ( have_posts() ) è probabilmente superfluo.

Modifica

Capisco che la query viene invocata da the_post(), giusto? E se esiste while(have_posts()), la query non avviene se non ci sono post.

Per capire cosa succede, bisogna guardare l'ordine delle azioni di WordPress. Partendo da wp_loaded (e omettendone alcune per chiarezza):

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

Quindi, cosa succede e in quale ordine?

  • La query viene invocata:
    • parse_query
    • pre_get_posts
    • wp
  • Il template viene selezionato:
    • template_redirect
  • Il template viene caricato/visualizzato. Le seguenti azioni vengono attivate dal template:
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Quindi, the_post, attivato da the_post(), avviene molto dopo che la query è stata analizzata, i post sono stati recuperati e il template è stato caricato.

Sono molto grato che tu abbia fornito molte informazioni che non conoscevo, ma non è questo quello che ho chiesto.

Oh, ma credo che sia esattamente quello che hai chiesto.

La vera domanda è: cos'è un ritorno valido di una query? Per contesti come l'indice dell'archivio di categoria, la query è valida e il template di categoria viene caricato se l'ID della categoria richiesta esiste, anche se non ci sono post assegnati a quella categoria.

Perché? Perché la query analizzata è (se ricordo bene) &cat={ID} - che è una query valida anche se non ci sono post assegnati a quella categoria, e quindi non restituisce un 404 durante l'analisi.

In quel caso, ottieni una query valida e un file template caricato, ma nessun post. Pertanto, if ( have_posts() ) è, infatti rilevante. Ecco un esempio: la categoria esiste, ma non ha post assegnati. Il file template della categoria viene caricato, con if ( have_posts() ) che restituisce false.

Questo non vale per le query che includono una variabile post (&p={ID}) come i singoli post del blog e le pagine statiche, perché il post non esisterà realmente e, quando analizzata, la query non restituirà un oggetto valido.

Modifica 2

Se capisco bene, se non c'è if(have_posts()) in un template di categoria e la categoria non ha post, allora restituisce 404.php, anche se dovrebbe restituire category-sample.php senza post. È corretto?

No. Ricorda: il template viene selezionato a template_redirect. Quindi, se la query è valida, viene caricato il file template appropriato. Se la query non è valida, viene caricato il template 404.

Quindi, una volta che un template è stato caricato - ad esempio il template di categoria - quando viene visualizzato il loop, il template non cambia.

Guarda di nuovo l'ordine delle azioni:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect - il template viene scelto e caricato qui. Questo è il punto di non ritorno del template. Il template non può cambiare dopo questo punto.
  • ...
  • the_post - i dati del post vengono impostati qui, come parte della chiamata del loop. Questo viene chiamato all'interno del template, e il template non cambia in base ai dati disponibili nell'oggetto della query

Modifica finale

E sto affermando che while verifica l'esistenza dei post, perché dovrei eseguire lo stesso test due volte. Questa è la mia domanda fin dal primo punto che ho posto solo su questo.

E con questo, finalmente capisco: fin dall'inizio, la tua domanda non aveva nulla a che fare con WordPress o il WordPress Loop. Stai chiedendo se è necessario racchiudere un qualsiasi loop PHP while all'interno di un condizionale if che verifica la stessa condizione.

Questa domanda è al di fuori dell'ambito di WPSE, ma spiegherò brevemente:

Un condizionale if è una valutazione binaria: è true o false, e ciò che accade all'interno di quel condizionale viene eseguito una volta.

Un condizionale while è un loop: rimane vero per un periodo discreto, basato su un qualche tipo di contatore; e ciò che accade all'interno di quel condizionale viene eseguito più volte - una per ogni iterazione del contatore.

Quindi, supponiamo che tu voglia visualizzare un elenco non ordinato di elementi, se la lista di elementi è popolata. Se usi un loop while e ometti il wrapper if, il tuo markup sarà così:

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

E se list_of_things() fosse vuoto, l'output renderizzato sarebbe:

<ul>
</ul>

Il che lascia un markup non necessario (e non valido).

Ma se aggiungi un wrapper condizionale if, puoi fare così:

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

E se list_of_things() fosse vuoto, non verrebbe visualizzato alcun markup.

Questo è solo un esempio. Ci sono molti utilizzi per quel wrapper condizionale if, e il wrapper condizionale if serve a uno scopo completamente diverso rispetto al loop while.

9 ott 2013 17:02:05
Commenti

Nei miei template di post/pagina singoli, da molto tempo, uso solo the_post(); perché anche il while è superfluo. +1 per la completezza delle informazioni.

gmazzap gmazzap
9 ott 2013 20:00:59

@G.M. Forse rimuovere l'istruzione if( have_posts() ) ha senso (è quello che sto cercando di capire), ma non usare semplicemente the_post() nelle pagine singole!

Sunyatasattva Sunyatasattva
12 ott 2013 23:53:37

@ChipBennett Tutto considerato, pensi che sia sicuro rimuovere la condizione if( have_post() ) prima del ciclo completo nel contesto dei file di template single-*.php e page-*.php?

Sunyatasattva Sunyatasattva
12 ott 2013 23:55:00

"Sicuro" in questo contesto non ha un significato definitivo.

Chip Bennett Chip Bennett
13 ott 2013 00:05:38
1
11

È davvero impossibile migliorare la risposta di Chip, ma per andare direttamente al punto:

Usa la parte if se vuoi che appaia qualcosa di diverso quando non ci sono post. Questo è particolarmente utile, ad esempio, su una pagina di archivio per data o categoria. Se qualcuno naviga su una pagina che non contiene post, è utile mostrare un messaggio che lo comunichi, piuttosto che non mostrare nulla, dato che il loop non viene eseguito.

if ( have_posts() ):
  // Sì, abbiamo dei post, quindi eseguiamo il loop.
  while ( have_posts() ) : the_post();
  // esegui il tuo loop
  endwhile;
else :
  // No, non abbiamo alcun post, quindi potremmo mostrare un messaggio gentile
  echo "<p class='no-posts'>" . __( "Spiacenti, al momento non ci sono post disponibili." ) . "</p>";
endif;
16 ott 2013 04:18:26
Commenti

E questo è tutto ciò che c'è da sapere.

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

Potrebbero esserci alcune considerazioni non incluse nelle risposte fino ad ora. Non è consigliabile omettere l'istruzione if.

L'istruzione if è comunemente utilizzata per:

  • restituire qualcosa come nessun articolo trovato per indicare che la categoria in questione non ha articoli assegnati.
  • decidere se il codice HTML circostante (come un ul) debba essere generato prima e dopo gli articoli.

Cosa succede se viene aggiunto un nuovo hook?

Un altro possibile problema del non utilizzare l'istruzione if è che se il team di WordPress decidesse di aggiungere un nuovo hook che viene attivato alla prima chiamata di $wp_query->have_posts(), questo verrebbe attivato nel momento sbagliato. E se ciò causasse comportamenti imprevisti, sarebbe colpa tua per non aver seguito correttamente le specifiche.

Gli altri sviluppatori si aspettano di vedere una struttura specifica per il loop di WordPress

Suppongo che gli altri sviluppatori si aspettino di vedere l'intero loop di WordPress. Quindi forse è una cattiva idea farli cercare un'istruzione if che non c'è.

28 nov 2019 13:24:39
2
-1

Vedo questa come una questione fondamentale della teoria delle strutture di controllo. Il blocco racchiuso all'interno del ciclo while non viene eseguito nemmeno una volta se la condizione (have_posts()) risulta falsa al primo valutamento.

Quindi, lo scopo di if ( have_posts() ) nel loop di WordPress è solo quello di eseguire la funzione have_posts() una volta prima che la condizione del while venga valutata. Se have_posts() non ha effetti collaterali, allora if ( have_posts() ) è completamente inutile. Se have_posts() ha effetti collaterali, potresti semplificare come segue:

<?php have_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Spiacenti, nessun articolo corrisponde ai tuoi criteri.'); ?></p>
<?php endif; ?>
24 ott 2014 01:59:17
Commenti

Quella semplificazione non è PHP valido, hai un'istruzione else che non è collegata a nessuna if. Nella migliore delle ipotesi è difficile da leggere

Tom J Nowell Tom J Nowell
24 ott 2014 02:27:59

Il if è lì proprio a causa dell'else che segue. Nessun altro motivo. Se non ci sono post, mostrare un bel messaggio "nessun post" è meglio che non mostrare nulla.

Otto Otto
24 ott 2014 03:13:09