Где следует сбросить postdata?
Я искал это в разделе "Вопросы и ответы", но не смог его найти. Когда я читаю ответы по всему сайту, я вижу wp_reset_postdata()
, размещенные в нескольких областях с условным have_posts()
и вне условного все вместе. Когда я прочитал документацию по wp_reset_postdata()
все, что в нем говорится, это:
После циклического выполнения отдельного запроса эта функция восстанавливает $post global в текущую запись в основном запросе.
С фрагментом из:
<?php
// example args
$args = array( 'posts_per_page' => 3 );
// the query
$the_query = new WP_Query( $args );
?>
<?php if ( $the_query->have_posts() ) : ?>
<!-- start of the secondary loop -->
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<?php the_title(); ?>
<?php the_excerpt(); ?>
<?php endwhile; ?>
<!-- end of the secondary loop -->
<!-- put pagination functions here -->
<!-- reset the main query loop -->
<?php wp_reset_postdata(); ?>
<?php else: ?>
<p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php endif; ?>
Но когда я ссылаюсь на другие способы, такие как " Как исправить разбивку на страницы для пользовательских циклов? "это после условного:
// Output custom query loop
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
// Loop output goes here
endwhile;
endif;
// Reset postdata
wp_reset_postdata();
Не было бы уместно сделать это впоследствии, а не в рамках условия have_posts()
, потому что, если вы используете оператор else, аргументы не сбрасываются, если у вас нет сообщений. Итак, мой вопрос в том, куда следует wp_reset_postdata()
идти?
3 answers
Краткая версия:
Как сказал Том Дж. Ноуэлл,
Вы не должны убирать, если нечего убирать
Длинная версия:
Однако, если вы поместите wp_reset_postdata()
после (или вне) цикла, он все равно будет работать отлично. Я использовал эту функцию в различных сценариях, включая что-то вроде этого:
dynamic_sidebar( 'main-sidebar' );
wp_reset_postdata();
Причина заключалась в том, что какой-то виджет запрашивал сообщения, не убирая за собой.
Просто имейте в виду, какой запрос вы хотите сбросить. В примере Тома, независимо от того, находится ли wp_reset_postdata
в операторе if
или нет, как только он будет вызван, у вас возникнут проблемы, потому что он напрямую вернется к основному сообщению вместо родительского пользовательского цикла.
Что делает функция, так это указывает объекту WP_Query
восстановить текущую запись в глобальную область. Поскольку это функция, а не метод, то есть единственный объект, с которым она работает - глобальный $wp_query
экземпляр WP_Query
объект.
Если у вас есть пользовательские циклы, в которых вы используете недавно сгенерированный WP_Query
, вам следует использовать метод reset_postdata
этого запроса:
$pages = new WP_Query( 'post_type=page' );
while( $pages->have_posts() ) {
$pages->the_post();
// Page title
echo '<h1>'; the_title(); echo '</h1>';
$books = new WP_Query( 'post_type=book&...' );
if( $books->have_posts() ) {
while( $books->have_posts() ) {
$books->the_post();
// Book title
echo '<li>'; the_title(); echo '</li>';
}
// Don't go back to the global post, go back to the "page"
// wp_reset_postdata();
$pages->reset_postdata();
}
// Page content
the_content();
}
// Finally, reset the main query
wp_reset_postdata();
Надеюсь, это подводит итог:)
Вы сделали это правильно! Это неправильный пример. К сожалению, почти все примеры запросов имеют эту проблему
Обычно размещение его после условного не имеет вредных последствий, но при вложении циклов это может вызвать проблемы в крайних случаях. Для 99,9 % случаев использования это не проблема.
Поместив его в условное условие, вы обеспечили сброс данных postdata только в том случае, если они были изменены.
Рассмотрим этот крайний случай:
while( have_posts() ) {
the_post();
... stuff...
$q = new WP_Query( $args );
if ( $q->have_posts() ) {
while( $q->have_posts() ) {
$q->the_post();
the_title();
$related_posts = new WP_Query( $args2 );
if ( $related_posts->have_posts() ) {
while( $related_posts->have_posts() ) {
$related_posts->the_post();
//
}
}
wp_reset_postdata();
the_content();
}
}
wp_reset_postdata();
}
Здесь мы делаем вложенный цикл для извлечения связанных записей, но обратите внимание, что произойдет, если связанные записи не будут найдены и $related_posts->have_posts()
вернет false
, данные post будут сброшены обратно в основной цикл, и вы получите содержимое публикации основных запросов, а не запрос $q
Обычно я использую его вне оператора if($query->have_posts())
. Таким образом, вы можете быть уверены, что даже если сообщения не будет, он сбросит запрос. У меня нет никаких проблем с размещением его после (и снаружи) оператора if($query->have_posts())
.