Три способа сбросить цикл в WordPress: wp_reset_postdata, wp_reset_query и rewind_posts
Тщательный контроль над выполнением циклов – одно из неоспоримых преимуществ системы WordPress. Как только речь заходит о настройке различных параметров или работе с множественными циклами, разработчик должен получить возможность сброса циклов. Справиться с этим позволяют три тега шаблонов: wp_reset_postdata(), wp_reset_query() и rewind_posts().
Первый из них, wp_reset_postdata(), позволяет вернуть глобальную переменную $post к своему первоначальному состоянию в основном запросе. Тег шаблона особенно полезен при использовании с WP_Query; он позволяет изменить вывод циклов или создать множественные циклы на одной странице. Выглядит он следующим образом:
<?php wp_reset_postdata(); ?>
Насколько вы можете видеть, этот тег очень прост в своем применении: он не принимает никаких параметров и не возвращает никаких значений. Он просто сбрасывает данные записи после выполнения произвольного запроса. Скажем, к примеру, что у нас есть цикл WP_Query, находящийся в файле header.php темы:
$random_post = new WP_query();
$random_post->query('cat=3&showposts=1&orderby=rand');
while ($random_post->have_posts()) : $random_post->the_post();
<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
<img src="<?php echo get_post_meta($random_post->ID, 'featured', true); ?>">
</a>
endwhile;
Этот цикл показал бы случайную запись в заголовке, но он также изменил бы и объект запроса для любых других циклов на странице. Без исходных данных выполнение основного цикла с записями, который находится, скажем, в index.php, может привести к неожиданным результатам. К счастью, мы можем использовать wp_reset_postdata, чтобы вернуть объект запроса в его начальное состояние.
Для этого остаточно поместить wp_reset_postdata после всех своих произвольных циклов. Возвращаясь к нашему предыдущему примеру, чтобы сбросить цикл, достаточно применить wp_reset_postdata:
<a href="https://oddstyle.ru/?attachment_id=5542" rel="attachment wp-att-5542"><img src="https://oddstyle.ru/wp-content/uploads/2011/09/loopinfinity.jpg.png" alt="" title="loopinfinity.jpg" width="310" height="320" class="aligncenter size-full wp-image-5542" /></a>
$random_post = new WP_query();
$random_post->query('cat=3&showposts=1&orderby=rand');
while ($random_post->have_posts()) : $random_post->the_post();
<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
<img src="<?php echo get_post_meta($random_post->ID, 'featured', true); ?>">
</a>
endwhile;
wp_reset_postdata();
Тем самым мы избежим большинства неизвестных и непонятных ошибок, связанных с выполнением множественных циклов.
Wp_reset_postdata лучше всего использовать после циклов, созданных с помощью WP_Query.
Следующий тег шаблона, который мы рассмотрим, это wp_reset_query(). Функция wp_reset_query позволяет сбросить запрос, используемый в произвольных циклах. Эта функция, так же как и wp_reset_postdata, не принимает никаких параметров и не возвращает никаких значений. Она имеет следующий вид:
<?php wp_reset_query(); ?>
Эта функция была создана для предотвращения различных проблем с query_posts, как это описано в файле wp-includes/query.php:
/**
* Destroy the previous query and set up a new query.
*
* This should be used after {@link query_posts()} and before another {@link
* query_posts()}. This will remove obscure bugs that occur when the previous
* wp_query object is not destroyed properly before another is set up.
*
* @since 2.3.0
* @uses $wp_query
*/
Если мы посмотрим на функцию wp_reset_query в query.php, то увидим, что она использует дополнительную функцию wp_reset_postdata, описанную выше:
// destroy and reset the query
function wp_reset_query() {
unset($GLOBALS['wp_query']);
$GLOBALS['wp_query'] =& $GLOBALS['wp_the_query'];
wp_reset_postdata(); // <-- RESET QUERY
}
// restore the query
function wp_reset_postdata() {
global $wp_query;
if ( !empty($wp_query->post) ) {
$GLOBALS['post'] = $wp_query->post;
setup_postdata($wp_query->post);
}
}
Таким образом, обе функции wp_reset_query() и wp_reset_postdata() позволяют сбросить объект запроса путем восстановления глобальной переменной $post, однако wp_reset_query идет несколько дальше – эта функция фактически уничтожает предыдущий запрос перед совершением возложенной на нее задачи. Пример ниже иллюстрирует ее использование:
<?php query_posts('posts_per_page=3');
if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php endwhile; endif; ?>
<?php wp_reset_query(); ?>
Таким образом, функцию wp_reset_query лучше всего использовать после цикла query_posts, чтобы сбросить различные данные, оставшиеся после произвольного запроса.
Последняя, третья функция – это rewind_posts(). Она позволяет перемотать цикл в конец, что позволит вам снова использовать тот же самый запрос. Как и две предыдущие функции, rewind_posts() не принимает параметров и не возвращает значений.
<?php rewind_posts(); ?>
Чтобы понять, как использовать rewind_posts(), давайте предположим, что мы хотим использовать один и тот же запрос в двух различных местах на странице. Допустим, мы хотим вывести на экран заголовки записей в первом цикле, и содержимое записей во втором цикле. Чтобы использовать те же самые записи в первом цикле и во втором цикле, мы включаем rewind_posts после первого цикла:
if (have_posts()) : while (have_posts()) : the_post(); ?> <h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1> <?php endwhile; endif; ?> <?php rewind_posts(); ?> <?php while (have_posts()) : the_post(); ?> <?php the_content(); ?> <?php endwhile; ?>
Если wp_reset_query и wp_reset_postdata сбрасывают весь объект запроса, то rewind_posts сбрасывает счетчик записей, как это и указано в файле wp-includes/query.php:
// rewind the posts and reset post index
function rewind_posts() {
$this->current_post = -1;
if ( $this->post_count > 0 ) {
$this->post = $this->posts[0];
}
}
Функцию rewind_posts лучше всего использовать для повторного использования одного и того же запроса на одной и той же странице.
http://digwp.com/2011/09/3-ways-to-reset-the-wordpress-loop/