Warum sollte ich setzen, wenn (have_posts ()), while (have_posts ()) nicht genug ist?

22

Ich habe eine Frage zu "the loop".

<?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 aus der Loop WordPress Codex Seite .

Warum sollte ich ifTeil setzen ? Es scheint, als ob es eine whileSchleife gibt, die gut funktioniert.

In welchem ​​Fall tritt ein Problem auf, wenn keine ifAussage vorliegt?

Bearbeiten

Ich habe die Antwort von @ Chip akzeptiert. aber ehrlich gesagt brauche ich nur den letzten teil.

Ich weiß jetzt, was ich von meiner Frage wissen wollte.

ifAnweisung ist nur dann erforderlich, wenn Sie eine Kopf- oder Fußzeile einfügen möchten, die nur einmal geschrieben werden soll. Wenn Sie den "Wrapper" nicht verwenden, ist die ifAnweisung nicht erforderlich.

Eisen und Sand
quelle
2
Ich habe abgestimmt, bevor ich den_Inhalt gelesen habe, der_Titel ist entscheidend!
Brasofilo
Hervorragende (endgültige) Bearbeitung. Die meisten Leute benutzen das Wenn und Während direkt hintereinander, ohne jemals ein Anderes zu benutzen. Wahrscheinlich wegen Copy & Paste.
Herbert Van-Vliet

Antworten:

29

Der WordPress-Vorlagenlader enthält in vielen Fällen die entsprechende kontextbezogene Vorlagendatei, auch wenn die Abfrage für diesen Kontext keine Beiträge zurückgibt. Beispielsweise:

  • Der Haupt-Blog-Index
  • Category Archive Index (Kategorie existiert, hat aber keine Beiträge)
  • Tag-Archiv-Index (Tag existiert, hat aber keine Beiträge)
  • Autorenarchivindex (Autor existiert, hat aber keine Beiträge)
  • Suchergebnis-Index

In diesen Fällen wird die entsprechende Vorlagendatei geladen, es werden jedoch keine Beiträge ausgegeben, da die Abfrage keine Beiträge zurückgibt.

Proof-of-Concept-Beispiele:

In diesen Kontexten ist es daher nützlich, dass die Vorlagendatei die if ( have_posts() )Bedingung enthält.

In anderen Kontexten wird die Vorlagendatei niemals geladen, wenn die Abfrage keine Beiträge zurückgibt. Beispielsweise:

  • Einzelner Blog-Beitrag
  • Statische Seite

In diesen Zusammenhängen if ( have_posts() )ist das wohl unnötig.

Bearbeiten

Ich verstehe, dass die Abfrage von the_post () aufgerufen wird, richtig? Wenn while (have_posts ()) vorhanden ist, wird die Abfrage nie ausgeführt, wenn kein Beitrag vorhanden ist.

Um zu verstehen, was los ist, müssen Sie sich die Reihenfolge der WordPress-Aktionen ansehen . Beginnen Sie mit wp_loaded(und lassen Sie einige aus Gründen der Klarheit weg):

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

Also, was passiert und in welcher Reihenfolge?

  • Die Abfrage wird aufgerufen:
    • parse_query
    • pre_get_posts
    • wp
  • Die Vorlage ist ausgewählt:
    • template_redirect
  • Die Vorlage wird geladen / ausgegeben. Die folgenden Aktionen werden von der Vorlage ausgelöst :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Also passiert the_post, ausgelöst durch the_post(), lange nachdem die Abfrage analysiert, Beiträge abgerufen und die Vorlage geladen wurde.

Ich bin sehr dankbar, dass Sie viele Informationen geben, die ich nicht kannte, aber das habe ich nicht gefragt.

Oh, aber ich glaube, dass es genau das ist , was Sie gefragt haben.

Die eigentliche Frage lautet: Was ist eine gültige Rückfrage ? Für Kontexte wie den Kategoriearchivindex ist die Abfrage gültig, und die Kategorieschablone wird geladen, wenn die abgefragte Kategorie-ID vorhanden ist, auch wenn dieser Kategorie keine Beiträge zugewiesen sind .

Warum? Weil die zu analysierende Abfrage (IIRC) ist. Dies &cat={ID}ist eine gültige Abfrage, auch wenn dieser Kategorie keine Posts zugewiesen sind , und führt daher beim Analysieren nicht zu 404.

In diesem Fall erhalten Sie eine gültige Abfrage und eine Vorlagendatei geladen, aber keine Beiträge . So if ( have_posts() ), ist in der Tat relevant. Auch hier ist ein Beispiel: Kategorie existiert, aber es wurden keine Beiträge zugewiesen. Die Kategorie-Vorlagendatei wird mit if ( have_posts() )Rückkehr geladenfalse .

Dies gilt nicht für Abfragen, die eine Beitragsvariable ( &p={ID}) enthalten, z. B. einzelne Blog-Beiträge und statische Seiten, da der Beitrag nicht vorhanden ist und die Abfrage beim Analysieren kein gültiges Objekt zurückgibt.

Bearbeiten 2

Wenn ich richtig verstehe, ob es kein if (have_posts ()) in einer Kategorieschablone gibt und die Kategorie keinen Beitrag hat, gibt sie 404.php zurück, obwohl es category-sample.php ohne Beitrag zurückgeben sollte. Ist das richtig?

Nein. Denken Sie daran: Die Vorlage ist unter ausgewählt template_redirect. Wenn die Abfrage also gültig ist, wird die entsprechende Vorlagendatei geladen. Wenn die Abfrage nicht gültig ist, wird die Vorlage 404 geladen.

Sobald also eine Vorlage geladen ist - z. B. die Kategorie-Vorlage -, ändert sich die Vorlage nach der Ausgabe der Schleife nicht mehr .

Sehen Sie sich die Reihenfolge der Aktionen noch einmal an:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- Vorlage wird hier ausgewählt und geladen. Dies ist der Vorlagenpunkt ohne Rückgabe . Die Vorlage kann nach diesem Zeitpunkt nicht mehr geändert werden.
  • ...
  • the_post- hier werden im rahmen des loop-aufrufs postdaten eingerichtet. Dies wird in der Vorlage aufgerufen und die Vorlage ändert sich nicht basierend auf den verfügbaren Daten im Abfrageobjekt

Final Edit

Und ich behaupte, dass, während die Existenz von Posts überprüft wird, warum ich denselben Test zweimal ausführen sollte. Das ist meine Frage von Anfang an, die ich nur danach gestellt habe.

Und damit verstehe ich endlich: Ihre Frage hatte die ganze Zeit nichts mit WordPress oder der WordPress-Schleife zu tun . Sie möchten eine beliebige PHP- whileSchleife in eine ifBedingung einschließen, die dieselbe Bedingung überprüft.

Diese Frage fällt nicht in den Anwendungsbereich von WPSE, aber ich werde kurz erklären:

Eine ifBedingung ist eine binäre Auswertung: Entweder trueoder false, und was in dieser Bedingung geschieht , wird einmal ausgeführt .

Eine whileBedingung ist eine Schleife : Sie bleibt für einen bestimmten Zeitraum gültig, basierend auf einer Art Zähler. und was innerhalb dieser Bedingung passiert , wird mehrmals ausgeführt - einmal für jede Iteration des Zählers.

Angenommen, Sie möchten eine ungeordnete Liste mit Dingen ausgeben, wenn die Liste mit Dingen gefüllt ist. Wenn Sie eine whileSchleife verwenden und den ifWrapper weglassen , sieht Ihr Markup folgendermaßen aus:

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

Und wenn list_of_things()leer wäre, wäre die gerenderte Ausgabe:

<ul>
</ul>

Was unnötiges (und ungültiges) Markup hinterlässt.

Wenn Sie jedoch einen ifbedingten Wrapper hinzufügen , können Sie Folgendes tun:

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

Und wenn list_of_things()leer wäre, würde überhaupt kein Aufschlag ausgegeben.

Das ist nur ein Beispiel. Es gibt viele Verwendungszwecke für diesen ifbedingten Wrapper, und der ifbedingte Wrapper erfüllt einen ganz anderen Zweck als die whileSchleife.

Chip Bennett
quelle
2
In meinen singulären Post / Page Templates verwende ich seit langem nur, the_post();weil auch das whileunnötig ist. +1 für die Vollständigkeit der Informationen.
gmazzap
@GM Möglicherweise macht das Entfernen der if( have_posts() )Anweisung Sinn (das versuche ich herauszufinden), aber nicht nur the_post()in einzelnen Seiten!
Sunyatasattva
@ChipBennett Glaubst du, dass es sicher ist, die if( have_post() )Bedingung vor der vollständigen Schleife im Kontext von single-*.phpund page-*.phpVorlagendateien zu entfernen ?
Sunyatasattva
1
"Sicher" hat in diesem Zusammenhang wirklich keine definitive Bedeutung.
Chip Bennett
10

Es ist wirklich unmöglich, die Antwort von Chip zu verbessern, aber nur auf den Punkt zu bringen:

Verwenden Sie den ifTeil, wenn etwas anderes angezeigt werden soll, wenn keine Beiträge vorhanden sind . Dies ist zum Beispiel auf einer Datums- oder Kategoriearchivseite besonders nützlich. Wenn jemand zu einer Seite navigiert, die keine Beiträge enthält, ist es schön, eine Nachricht zu haben, die dies sagt, und nicht nur, dass überhaupt nichts angezeigt wird, da die Schleife nie ausgeführt wird.

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
quelle
Und das ist alles was man wissen muss.
Herbert Van-Vliet
0

Es kann einige Überlegungen geben, die in den Antworten bisher nicht enthalten sind. Es wird nicht empfohlen, die if-Anweisung wegzulassen.

Die if-Anweisung wird häufig verwendet, um:

  • Geben Sie so etwas wie aus, no posts foundum anzuzeigen, dass der betreffenden Kategorie keine Artikel zugeordnet sind.
  • um zu entscheiden, ob das umgebende HTML (wie ein ul) vor und nach den Artikeln ausgegeben werden soll.

Was ist, wenn ein neuer Haken hinzugefügt wird?

Ein weiteres mögliches Problem, wenn die if-Anweisung nicht verwendet wird, besteht darin, dass ein neuer Hook, der beim ersten $wp_query->have_posts()Aufruf ausgelöst wird, zum falschen Zeitpunkt ausgelöst wird, wenn das WordPress-Team sich jemals dazu entschließt, einen neuen Hook hinzuzufügen . Und wenn dies zu unerwartetem Verhalten führt, liegt es an Ihnen, dass Sie die Spezifikation nicht ordnungsgemäß befolgen.

Andere Entwickler erwarten eine bestimmte Struktur für die WordPress-Schleife

Ich nehme an, andere Entwickler erwarten die gesamte WordPress-Schleife. Vielleicht ist es eine schlechte Idee, sie nach einer if-Anweisung suchen zu lassen, die nicht vorhanden ist.

RMo
quelle
-1

Ich sehe dies als eine grundlegende Frage der Kontrollstrukturtheorie. Der eingeschlossene Block innerhalb der while-Schleife wird nicht einmal ausgeführt, wenn condition (have_posts ()) das erste Mal als false ausgewertet wird.

Der Zweck if ( have_posts() )der WordPress-Schleife besteht also darin, die Funktion have_posts () nur einmal auszuführen, bevor die while-Bedingung ausgewertet wird. Wenn have_posts()keine Nebenwirkungen hat, dann if ( have_posts() )ist das völlig sinnlos. Wenn have_posts()Nebenwirkungen auftreten, können Sie dies wie folgt vereinfachen:

<?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
quelle
3
Diese Vereinfachung ist ungültiges PHP. Sie haben eine else-Anweisung, an die keine if-Anweisung angehängt ist. Bestenfalls ist es schwer zu lesen
Tom J Nowell
1
Das ifliegt daran das elsedanach. Kein anderer Grund. Wenn keine Beiträge vorhanden sind, ist es besser, eine nette Nachricht "Keine Beiträge" anzuzeigen, als nichts anzuzeigen.
Otto