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


22

Ho una domanda su "il ciclo".

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

Codice tratto dalla pagina del codice WordPress Loop .

Perché dovrei mettere ifparte? Sembra che ci sia un whileciclo, funzioni bene.

In quale caso si verifica un problema se non ci sono ifdichiarazioni?

modificare

Ho accettato la risposta di @ Chip. ma onestamente dicendo che ho bisogno solo dell'ultima parte.

Ora so cosa volevo sapere dalla mia domanda.

ifL'istruzione è solo quando necessario, se si desidera inserire un'intestazione o un piè di pagina che deve essere scritto una sola volta. se non si utilizza il "wrapper", la ifdichiarazione non è necessaria.


2
Ho votato prima di leggere the_content, the_title è decisivo!
brasofilo,

Eccellente (finale) modifica. La maggior parte delle persone usa if e direttamente dopo l'altro senza mai usare un altro. Probabilmente a causa di copia e incolla.
Herbert Van-Vliet,

Risposte:


29

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

  • L'indice principale dei post sul blog
  • Indice archivio categorie (la categoria esiste, ma non ha post)
  • Indice archivio tag (il tag esiste, ma non ha post)
  • Indice archivio autore (l'autore esiste, ma non ha post)
  • Indice dei risultati di ricerca

Pertanto, in questi casi, verrà caricato il file modello appropriato, ma non verranno emessi post, poiché la query non restituisce alcun post.

Esempi di prove concettuali:

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

In altri contesti, il file modello non verrà mai caricato se la query non restituisce alcun post. Per esempio:

  • Post di blog singolo
  • Pagina statica

In questi contesti, if ( have_posts() )probabilmente non è necessario.

modificare

Capisco che la query è invocata da the_post (), giusto? E se while (have_posts ()) esiste, la query non si verifica mai se non ci sono post.

Per capire cosa sta succedendo, devi guardare l'ordine delle azioni di WordPress . A partire da wp_loaded(e omettendone alcuni 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 sta succedendo e in quale ordine?

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

Quindi, the_postattivato da the_post(), accade molto tempo dopo che la query viene analizzata, i post vengono recuperati e il modello viene caricato.

Sono molto grato che tu abbia dato molte informazioni che non sapevo, ma non è quello che ti ho chiesto.

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

La vera domanda è: che cos'è un ritorno di query valido ? Per contesti come l'indice di archivio delle categorie, la query è valida e il modello di categoria viene caricato, se esiste l'ID categoria richiesto, anche se non ci sono post assegnati a quella categoria .

Perché? Perché la query da analizzare è (IIRC) &cat={ID}- che è una query valida anche se non ci sono post assegnati a quella categoria , e quindi non risulta in un 404 al momento dell'analisi.

In tal caso, ottieni una query valida e un file modello caricato, ma nessun post . Così, if ( have_posts() ), è, di fatto rilevanti. Ancora una volta, ecco un esempio: la categoria esiste, ma non ha post assegnati. Il file del modello di categoria viene caricato e if ( have_posts() )restituitofalse .

Ciò non sarà valido per le query che includono una variabile post ( &p={ID}) come singoli post di blog e pagine statiche, poiché il post non esisterà effettivamente e, se analizzato, la query non restituirà un oggetto valido.

Modifica 2

Se capisco giustamente se non esiste if (have_posts ()) in un modello di categoria e la categoria non ha post, allora restituisce 404.php, anche se dovrebbe essere restituito category-sample.php senza post. È giusto?

No. Ricorda: il modello è selezionato in template_redirect. Pertanto, se la query è valida, viene caricato il file modello appropriato. Se la query non è valida, viene caricato il modello 404.

Quindi, una volta caricato un modello, ad esempio il modello di categoria, una volta che il ciclo è stato emesso, il modello non cambia .

Guarda di nuovo l'ordine delle azioni:

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

Modifica finale

E sto affermando che, mentre controlla l'esistenza dei post, perché dovrei eseguire lo stesso test due volte. Questa è la mia domanda dal primo punto che ho chiesto solo a tale proposito.

E con ciò, finalmente capisco: la tua domanda non ha avuto niente a che fare con WordPress o WordPress Loop . Stai chiedendo di racchiudere qualsiasi whileloop PHP arbitrario all'interno di un ifcondizionale che controlla la stessa condizione.

Questa domanda non rientra nell'ambito di applicazione di WPSE, ma spiegherò brevemente:

Un ifcondizionale è una valutazione binaria: è uno trueo false, e ciò che accade all'interno di quel condizionale viene eseguito una volta .

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

Quindi, supponiamo che tu voglia produrre un elenco non ordinato di cose, se l'elenco delle cose è popolato. Se usi un whileciclo e ometti il ifwrapper, il markup sarebbe simile al seguente:

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

Ciò lascia un markup non necessario (e non valido).

Ma se aggiungi un ifwrapper condizionale, puoi farlo:

<?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 emesso alcun markup.

Questo è solo un esempio. Esistono molti usi per quel ifwrapper condizionale e il ifwrapper condizionale ha uno scopo completamente diverso rispetto al whileloop.


2
Nei miei modelli di post / pagina singolari, da molto tempo, uso solo the_post();perché anche ciò whilenon è necessario. +1 per la completezza delle informazioni.
gmazzap

@GM Forse rimuovere la if( have_posts() )frase ha senso (è quello che sto cercando di scoprire), ma non usare solo the_post()in pagine singole!
Sunyatasattva,

@ChipBennett Tutto considerato, pensi che sia sicuro rimuovere la if( have_post() )condizione prima del ciclo completo nel contesto di single-*.phpe page-*.phpfile modello?
Sunyatasattva,

1
"Sicuro" non ha davvero un significato definitivo in questo contesto.
Chip Bennett,

10

È davvero impossibile migliorare la risposta di Chip, ma solo per inseguire:

Usa la ifparte se vuoi che venga visualizzato qualcosa di diverso quando non ci sono post . Ciò è particolarmente utile, ad esempio, in una pagina di archivio di date o categorie. Se qualcuno accede a una pagina che non ha post, è bello avere un messaggio che lo dice, piuttosto che non appare nulla, perché il loop non viene mai eseguito.

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;

E questo è tutto ciò che bisogna sapere.
Herbert Van-Vliet,

0

Potrebbero esserci alcune considerazioni che finora non sono state incluse nelle risposte. Non è consigliabile omettere l'istruzione if.

L'istruzione if è comunemente usata per:

  • output qualcosa del genere no posts foundper indicare che alla categoria in questione non sono stati assegnati articoli.
  • per decidere se l'html circostante (come un ul) debba essere prodotto prima e dopo gli articoli.

Cosa succede se viene aggiunto un nuovo hook?

Un altro possibile problema di non utilizzare l'istruzione if è che se il team di wordpress avesse mai deciso di aggiungere un nuovo hook che si innesca alla prima $wp_query->have_posts()chiamata, si innescherebbe nel momento sbagliato. E se ciò causa comportamenti imprevisti, sarebbe colpa tua se non seguirai correttamente le specifiche.

Altri sviluppatori si aspettano di vedere una struttura specifica per il ciclo di wordpress

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


-1

Vedo questo come una questione fondamentale della teoria della struttura di controllo. Il blocco racchiuso nel ciclo while non viene eseguito nemmeno una volta se la condizione (have_posts ()) viene valutata come falsa la prima volta.

Quindi, lo scopo di if ( have_posts() )nel ciclo di WordPress è quello di eseguire la funzione have_posts () una volta prima di valutare la condizione while. Se have_posts()non ha effetti collaterali, allora if ( have_posts() )è totalmente 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('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

3
Quella semplificazione non è PHP valida, hai un'istruzione else che non ha un'istruzione if allegata. Nella migliore delle ipotesi è difficile da leggere
Tom J Nowell

1
L' ifè lì a causa del elsedopo di esso. Nessun altro motivo. Se non ci sono post, visualizzare un bel messaggio "no post" è meglio che non visualizzare nulla.
Otto,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.