Зачем мне ставить if (have_posts ()), а while (have_posts ()) недостаточно?


22

У меня вопрос по поводу "петли".

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

Код взят со страницы Кодекса The Loop WordPress .

Почему я должен поставить ifчасть? Кажется, если есть whileпетля, работает нормально.

В каком случае возникает проблема, если нет ifзаявления?

редактировать

Я принял ответ @ Чипа. но, честно говоря, мне нужна только последняя часть.

Теперь я знаю, что я хотел узнать из моего вопроса.

ifЗаявление только в случае необходимости, если вы хотите поставить верхний или нижний колонтитул, который должен быть записан только один раз. если вы не используете «обертку», то ifутверждение не нужно.


2
Я проголосовал, прежде чем читать the_content, the_title является решающим!
brasofilo

Отличное (окончательное) редактирование. Большинство людей используют if и while непосредственно друг за другом, не используя else. Вероятно, из-за копирования и вставки.
Герберт Ван-Влит

Ответы:


29

Загрузчик шаблонов WordPress будет включать соответствующий контекстный файл шаблона во многих случаях, даже если запрос для этого контекста не возвращает сообщений. Например:

  • Индекс главных сообщений в блоге
  • Индекс архива категории (категория существует, но не имеет сообщений)
  • Индекс архива тегов (тег существует, но не имеет сообщений)
  • Указатель архива автора (Автор существует, но не имеет сообщений)
  • Индекс результатов поиска

Таким образом, в этих случаях будет загружен соответствующий файл шаблона, но сообщения не будут выводиться, поскольку запрос не возвращает сообщений.

Примеры подтверждения концепции:

Таким образом, в этих контекстах полезно, чтобы файл шаблона включал if ( have_posts() )условные выражения.

В других контекстах файл шаблона никогда не будет загружен, если запрос не возвращает сообщений. Например:

  • Одиночная запись в блоге
  • Статическая страница

В этих условиях, if ( have_posts() )вероятно, нет необходимости.

редактировать

Я понимаю, что запрос вызывается the_post (), верно? И если while (have_posts ()) существует, запрос никогда не выполняется, если нет записи.

Чтобы понять, что происходит, вы должны посмотреть на порядок действий WordPress . Начиная с wp_loaded(и опуская некоторые для ясности):

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

Итак, что происходит и в каком порядке?

  • Запрос вызывается:
    • parse_query
    • pre_get_posts
    • wp
  • Шаблон выбран:
    • template_redirect
  • Шаблон загружен / вывод. Следующие действия выполняются шаблоном :
    • get_header
    • wp_head
    • the_post
    • dynamic_sidebar
    • get_footer
    • wp_footer

Таким образом, the_postсрабатывание the_post()происходит спустя много времени после анализа запроса, получения сообщений и загрузки шаблона.

Я очень благодарен, что вы даете много информации, которую я не знал, но это не то, что я спросил.

О, но я верю, что это именно то , что вы спросили.

Реальный вопрос: что такое верный запрос возврата ? Для таких контекстов, как индекс архива категории, запрос действителен, и шаблон категории загружается, если запрашиваемый идентификатор категории существует, даже если для этой категории нет записей .

Зачем? Поскольку анализируемый запрос - это (IIRC), &cat={ID}который является допустимым запросом, даже если нет записей, назначенных этой категории , и, следовательно, не приводит к 404 при разборе.

В этом случае вы получите правильный запрос и загруженный файл шаблона, но ни одной записи . Таким образом, if ( have_posts() ), , на самом деле актуальна. Опять же, вот пример: категория существует, но не имеет назначенных сообщений. Файл шаблона категории загружается, с if ( have_posts() )возвратомfalse .

Это не будет справедливо для запросов, которые включают переменную post ( &p={ID}), такую ​​как отдельные сообщения в блоге и статические страницы, потому что сообщение фактически не существует, и при разборе запрос не вернет допустимый объект.

Edit 2

Если я правильно понимаю, что в шаблоне категории нет if (have_posts ()), а в категории нет записей, тогда возвращается 404.php, даже если должен возвращаться category-sample.php без записи. Это правильно?

Помните: шаблон выбран в template_redirect. Так что если запрос допустим, то загружается соответствующий файл шаблона. Если запрос недействителен, загружается шаблон 404.

Таким образом, после загрузки шаблона, например шаблона категории, после вывода цикла шаблон не изменяется .

Посмотрите еще раз на порядок действий:

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- шаблон выбран и загружен здесь. Это шаблонная точка невозврата . Шаблон не может измениться после этой точки.
  • ...
  • the_post- postdata устанавливается здесь как часть вызова цикла. Это вызывается внутри шаблона , и шаблон не изменяется в зависимости от доступных данных в объекте запроса.

Окончательное редактирование

И я утверждаю, что, хотя проверяет наличие постов, зачем мне запускать один и тот же тест дважды. Это мой вопрос с первого момента, который я спрашивал только об этом.

И с этим я наконец-то понимаю: ваш вопрос не имел ничего общего с WordPress или циклом WordPress . Вы просите обернуть любой произвольный whileцикл PHP внутри ifусловия, которое проверяет то же условие.

Этот вопрос выходит за рамки WPSE, но я кратко объясню:

ifУсловно является бинарной оценкой: или trueили false, и того, что происходит внутри этого Conditional выполняется один раз .

whileУсловный является циклом : он остается верным в течение некоторого дискретного периода, основываясь на каком - то счетчик; и то, что происходит внутри этого условия, выполняется несколько раз - один раз для каждой итерации счетчика.

Итак, допустим, что вы хотите вывести неупорядоченный список вещей, если этот список заполнен. Если вы используете whileцикл и опускаете ifоболочку, ваша разметка будет выглядеть так:

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

И если бы он list_of_things()был пустым, вывод был бы:

<ul>
</ul>

Что оставляет ненужную (и недействительную) разметку.

Но если вы добавите в ifусловную оболочку, вы можете сделать это:

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

А если бы он list_of_things()был пустым, никакая разметка вообще не выводилась бы.

Это только один пример. Существует много вариантов использования этой ifусловной оболочки, и ifусловная оболочка служит совершенно иным целям, чем whileцикл.


2
В моих шаблонах постов / страниц я использую только долгое время только the_post();потому, что в whileних нет необходимости. +1 за полноту информации.
gmazzap

@GM Возможно, удаление if( have_posts() )заявления имеет смысл (это то, что я пытаюсь выяснить), но не используйте его только the_post()на отдельных страницах!
Sunyatasattva

@ChipBennett Как вы считаете, безопасно ли удалять if( have_post() )условие перед полным циклом в контексте файлов шаблона single-*.phpи page-*.php?
Суньятасаттва

1
«Сейф» действительно не имеет окончательного значения в этом контексте.
Чип Беннетт

10

Действительно невозможно улучшить ответ Чипа, но просто перейти к преследованию:

Используйте ifчасть, если вы хотите, чтобы что-то другое отображалось, когда нет сообщений . Это особенно полезно, например, на странице архива даты или категории. Если кто-то переходит на страницу, на которой нет сообщений, было бы хорошо иметь сообщение, в котором говорится так, а не просто ничего не отображаться вообще, потому что цикл никогда не выполняется.

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;

И это все, что нужно знать.
Герберт Ван-Влит

0

Могут быть некоторые соображения, которые пока не включены в ответы. Не рекомендуется опускать оператор if.

Оператор if обычно используется для:

  • выведите что-то вроде того, no posts foundчтобы указать, что рассматриваемая категория не имеет назначенных статей.
  • решить, следует ли выводить окружающий html (например, ul) до и после статей.

Что если новый хук добавлен?

Другая возможная проблема неиспользования оператора if заключается в том, что если команда WordPress решила добавить новый хук, который срабатывает при первом $wp_query->have_posts() вызове, он сработает в неподходящее время. И если это приведет к неожиданному поведению, это будет ваша вина за то, что вы не следовали спецификации должным образом.

Другие разработчики ожидают увидеть конкретную структуру для цикла WordPress

Я предполагаю, что другие разработчики ожидают увидеть весь цикл WordPress. Поэтому, может быть, это плохая идея, чтобы они искали оператор if, которого там нет.


-1

Я рассматриваю это как фундаментальный вопрос теории структуры управления. Закрытый блок в цикле while не выполняется ни разу, если условие (have_posts ()) в первый раз оценивается как ложное.

Таким образом, цель if ( have_posts() )цикла WordPress - выполнить функцию have_posts () только один раз до того, как будет выполнено условие while. Если have_posts()не имеет побочных эффектов, то if ( have_posts() )совершенно бессмысленно. Если have_posts()есть побочные эффекты, вы можете упростить это следующим образом:

<?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
Это упрощение недопустимо в PHP, у вас есть оператор else, который не имеет прикрепленного оператора if. В лучшем случае это трудно читать
Том Дж. Новелл

1
Это ifтам из-за elseпосле этого. Нет другой причины. Если сообщений нет, тогда показывать приятное сообщение «нет сообщений» лучше, чем ничего.
Отто
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.