Три способа сбросить цикл в WordPress: wp_reset_postdata, wp_reset_query и rewind_posts

Дата публикации:Сентябрь 13, 2011

Тщательный контроль над выполнением циклов — одно из неоспоримых преимуществ системы 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="http://oddstyle.ru/?attachment_id=5542" rel="attachment wp-att-5542"><img src="http://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/

Поделиться

Один комментарий

  1. Дмитрий says:

    Одного не могу понять, почему меняются исходные данные. Мы ведь всё помещаем в произвольную переменную $random_post, не затрагивая других. Не могу это уяснить.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.