Обратите внимание, что эта функция только для основного цикла. Если мы работаем с дополнительным циклом при помощи WP_Query, то используем метод класса WP_Query::have_posts()
.
Ещё раз о том, что делает функция, подробнее:
- Когда вы используете её в качестве условия на странице
if( have_posts() )
– тут всё просто, если есть посты на странице –return true
, нет –false
. - Когда используется в цикле
while( have_posts() )
, ситуация становится интереснее. Как вы знаете, у нас есть функции для вывода параметров текущего поста, например the_title(), the_permalink(). Как они определяют, что это тот самый пост? При помощи функции the_post(), которая при каждой итерации цикла хватает следующий пост в очереди. А что происходит, когда очередь заканчивается? – тогдаwhile ( have_posts() )
возвращаетfalse
и цикл завершается. Однако (!) в то же время функцияhave_posts()
также делает и сброс значения текущего поста, возвращаясь к самому первому на этой странице! 🎉
Пример 1. Стандартно
В шаблонах тем WordPress можно часто встретить подобную запись:
if( have_posts() ) : while( have_posts() ) : the_post(); // тут обычно что-то происходит endwhile; else : echo 'Ничего не найдено на этой странице'; endif;
- Сначала при помощи условия
if ( have_posts() ) :
, мы проверяем, есть ли вообще посты на этой странице? Это может быть страница рубрики, или главная – неважно. Если эта, предположим рубрика, пуста, то выводим «Ничего не найдено…» и больше ничего не делаем. - На строчках 3-7 мы проходим циклом по всем постам на странице «до тех пор, пока есть посты» и что-то делаем в теле цикла, например выводим заголовок поста через the_title() или же подключаем HTML/PHP темплейт записи функцией get_template_part() (это довольно часто встречается в темах).
- Если убрать на 3-й строке функцию the_post(), то мы получим бесконечный цикл, потому что что the_post() сдвигает значение ткущего поста к следующему и в один момент, когда ей уже будет некуда сдвигать,
have_posts()
вернётfalse
, а если не производить «этот сдвиг», тоhave_posts()
всегда будет возвращатьtrue
.
Пример 2. Множество циклов
Такую запись можно встретить не часто, однако она важна для понимания сути.
while( have_posts() ) : the_post(); // тут обычно что-то происходит endwhile; while( have_posts() ) : the_post(); // невероятные вещи продолжают происходить endwhile;
Как такая запись вообще возможна?
Об этом я и говорил в самом начале, когда упомянул сброс цикла. Когда функция the_post() доводит цикл до конца, у нас происходит сразу две вещи:
have_posts()
возвращаетfalse
,have_posts()
сбрасывает цикл, устанавливая значение текущего поста на самый первый пост на странице;
Пример 3. Хитрое условие для последнего поста цикла
Или ещё можно сказать – для последней итерации цикла while ( have_posts() )
. Обычно, когда идёт разговор об итерациях цикла, первое, что приходит в голову (мою), это уроки информатики с переменными-счетчиками.
Но только не сегодня.
while( have_posts() ) : the_post(); // ... выводится пост например if( ! have_posts() ) { echo 'это последний пост цикла'; } endwhile;
Стоп! Не копируйте, прошу!
Что думаете про этот код? Норм или что-то смущает?
Представьте:
- Идёт последняя итерация цикла, выводится последний пост.
- Затем функция
have_posts()
(строка 5) определяет, что это последний пост, возвращаетfalse
, и соответственно выводится месседж «это последний пост цикла». - И вроде бы всё хорошо и цикл должен закончиться, однако
have_posts()
сбрасывает текущий пост цикла и всё начинается снова, так и не закончившись!
Как исправить? Вместо условия have_posts()
на 5-й строке используем другое условие:
global $wp_query; if( $wp_query->current_post + 1 == $wp_query->post_count ) { echo 'это последний пост цикла'; }
Источник: misha.blog