$post->ID не работает
У меня есть следующий код, и хотя get_the_ID() работает, $post->ID не работает, почему?
$the_query = new WP_Query( array(
'post_type' => 'custompost',
) );
while ( $the_query->have_posts() ) : $the_query->the_post();
echo $post->ID;
endwhile;
Чтобы использовать $post->ID, вам нужно объявить переменную $post как глобальную внутри цикла:
$the_query = new WP_Query( array(
'post_type' => 'custompost',
) );
while ( $the_query->have_posts() ) : $the_query->the_post();
global $post;
echo $post->ID;
endwhile;
Альтернативно, вы можете использовать функцию get_the_ID(), которая является рекомендуемым способом получения ID поста в WordPress.

Ваш цикл WP_Query неполный. Вы не проверяете, были ли найдены записи перед началом цикла, не выводите сообщение об их отсутствии и не очищаете данные после завершения. Кроме того, вы используете альтернативный синтаксис, который нарушает сопоставление скобок в IDE, усложняя себе жизнь.
Попробуйте добавить global $post;
следующим образом:
global $post;
$the_query = new WP_Query( array(
'post_type' => 'custompost'
) );
if($the_query->have_posts()){
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo $post->ID;
}
wp_reset_postdata();
}else {
echo 'записи не найдены';
}
При написании запросов важно быть последовательным и делать всё правильно. Поэтому я рекомендую ознакомиться с этими слайдами Эндрю Нацина, разработчика ядра WordPress в Automattic:
http://www.slideshare.net/andrewnacin/you-dont-know-query-wordcamp-netherlands-2012
Они расскажут, где уместно использовать каждый тип запроса, как их правильно применять и почему.
В приведённом выше коде я добавил условие if для проверки наличия записей и функцию wp_reset_postdata, которая позволяет продолжить использование основного запроса, очищая данные после пользовательского цикла.

Спасибо, глобальная переменная сработала. Как это работает? И что именно делает wp_reset_postdata()? Она всегда нужна?

Полагаю, $post
просто была вне области видимости. Что касается wp_reset_postdata()
- когда вы запускаете цикл, переменная $post изменяется, поэтому wp_reset_postdata() работает как отмена этих изменений, позволяя использовать несколько циклов внутри основного запроса без его нарушения.

Вам стоит посмотреть эти слайды: http://www.slideshare.net/andrewnacin/you-dont-know-query-wordcamp-netherlands-2012 Это невероятно полезная презентация по созданию запросов от Nacin, одного из основных разработчиков ядра WordPress, там всё объясняется

Я согласен со всем, кроме комментария о синтаксисе "other". В большинстве случаев мы будем выводить HTML внутри цикла while, поэтому синтаксис "other" обычно более подходящий. Ссылка на документацию по альтернативному синтаксису на случай, если кому-то интересно - http://php.net/manual/en/control-structures.alternative-syntax.php

Как выяснил Том Новелл, решение заключается в добавлении ссылки на global $post
.
Когда вы выполняете the_query->the_post()
, WordPress загружает первый результат запроса в глобальный объект $post
. Именно так он настраивает всё для стандартных тегов шаблонов:
the_title()
the_content()
the_excerpt
()- и т.д.
Обратите внимание, что мы не передаём никакие параметры в эти функции. Мы просто их вызываем. Каждая из этих функций внутри себя обращается к глобальному объекту $post
, чтобы обработать, подготовить и вывести нужные данные.
Внутри вашего цикла вы спокойно вызываете the_post()
, чтобы заполнить данные, но у вас нет ссылки на сами данные в области видимости вашего цикла. Если вы хотите избежать обращения к глобальному объекту $post
, вы можете использовать get_the_ID()
.
Как и другие теги шаблонов, упомянутые выше, get_the_ID()
получает данные из глобального объекта $post
внутри себя, так что вам не нужно делать это вручную.
Но если вы хотите сделать это самостоятельно, просто добавьте глобальную ссылку перед использованием $post
:
$the_query = new WP_Query( array(
'post_type' => 'custompost',
) );
while ( $the_query->have_posts() ) : $the_query->the_post();
global $post; // Добавьте эту строку, и всё заработает
echo $post->ID;
endwhile;
Что такое wp_reset_postdata()
?
Если вы создаёте несколько циклов (например, у вас есть основной цикл записей, но внутри него вызывается дополнительный цикл), вы можете использовать wp_reset_postdata()
, чтобы сбросить настройки.
По сути, the_post()
устанавливает глобальный объект $post
так, чтобы он содержал данные из запроса. the_query->the_post()
перезаписывает $post
данными из the_query
. wp_reset_postdata()
возвращает $post
к исходному запросу.
Таким образом, если вы используете вложенные или множественные циклы, wp_reset_postdata()
позволяет вернуться к циклу и объекту $post
, которые были доступны до вызова дополнительного the_query->the_post()
.
