Навіщо мені ставити, якщо (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; ?>

Код, взятий зі сторінки Loop WordPress Codex .

Чому я повинен ставити ifчастину? Здається, якщо є whileцикл, працює чудово.

У якому випадку виникає проблема, якщо немає ifзаяви?

Редагувати

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

Зараз я знаю, що хотів дізнатися із свого запитання.

ifОператор є лише в разі необхідності, якщо ви хочете поставити заголовок або колонтитул, який слід написати лише один раз. якщо ви не використовуєте "обгортку", тоді ifзаява не потрібна.


2
Я проголосував перед тим, як прочитати зміст, the_title є визначальним!
brasofilo

Відмінна (остаточна) редакція. Більшість людей користуються функцією "if" і "" прямо один за одним, не використовуючи жодного іншого. Ймовірно, через копіювати та вставляти.
Герберт Ван-Вліет

Відповіді:


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 .

Це не відповідає дійсності для запитів, що включають змінну публікації ( &p={ID}), таку як окремі публікації блогу та статичні сторінки, оскільки публікація насправді не існує, і при розборі запит не поверне дійсний об’єкт.

Редагувати 2

Якщо я правильно розумію, що якщо в шаблоні категорії немає (if_posts ()), а категорія не має посади, то вона повертає 404.php, навіть незважаючи на те, що вона повинна повернути категорію-sample.php без публікації. Це так?

Ні. Пам'ятайте: шаблон обраний на template_redirect. Тож якщо запит дійсний, то завантажується відповідний файл шаблону. Якщо запит недійсний, завантажується шаблон 404.

Отже, щойно шаблон завантажується - наприклад, шаблон категорії - щойно цикл виводиться, шаблон не змінюється .

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

  • parse_query
  • pre_get_posts
  • wp
  • template_redirect- тут обраний і завантажений шаблон. Це шаблон шаблону без повернення . Шаблон не може змінитися після цього пункту.
  • ...
  • the_post- тут налаштовано постдані, як частина виклику циклу. Це називається всередині шаблону , і шаблон не змінюється на основі наявних даних в об’єкті запиту

Остаточна редакція

І я стверджую, що, перевіряючи наявність дописів, чому я повинен запускати один і той же тест двічі. Це моє запитання з першого моменту, про яке я питав лише про це.

І з цим я нарешті розумію: все ваше запитання не мало нічого спільного ні з WordPress , ні з циклом WordPress . Ви запитуєте про загортання будь-якого довільного whileциклу PHP всередині ifумовного, що перевіряє те саме умова.

Це питання виходить за рамки WPSE, але я коротко поясню:

Умовне if- це двійкове оцінювання: воно trueабо false, і те, що відбувається всередині цього умовного, виконується один раз .

Умовним 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файлів шаблонів?
Sunyatasattva

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 () один раз до того, як буде проведено оцінку умови. Якщо 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, у вас є інше твердження, яке не додається, якщо оператор. У кращому випадку це важко читати
Том Дж. Ноуелл

1
ifТам через elseпісля нього. Іншої причини немає. Якщо публікацій немає, то відображати приємне повідомлення "без публікацій" краще, ніж нічого не показувати.
Отто
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.