Нужно ли использовать wp_reset_query() при вызове WP_Query в WordPress?
Я использую следующий код для получения записей:
<?php
$featuredPosts = new WP_Query();
$featuredPosts->query('showposts=5&cat=3');
while ($featuredPosts->have_posts()) : $featuredPosts->the_post(); ?>
<h1><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h1>
<div class="meta">
Автор: <?php the_author() ?>
</div>
<div class="storycontent">
<?php the_excerpt(); ?>
</div>
<?php endwhile; ?>
Нужно ли мне использовать wp_reset_query()
? Если да, то где его следует разместить?

Для самого WP_Query
это не обязательно, но необходимо (или, по крайней мере, является хорошей практикой), если вы используете связанные функции/методы (такие как the_post()
или setup_postdata()
), чтобы заполнить глобальные переменные вашими данными.
По сути, создание нового объекта WP_Query
— это просто извлечение данных, но использование его для запуска активного цикла и предоставления доступа к данным для тегов шаблонов изменяет окружение, поэтому хорошо сбросить всё обратно после завершения.
В целом — вызов этой функции не создаёт значительных накладных расходов, поэтому проще всегда вызывать её, чем решать, нужно ли это делать, или забыть о ней и столкнуться с загадочными ошибками.
Обновление
Функция wp_reset_postdata()
кажется более подходящим выбором. wp_reset_query()
сбрасывает глобальную переменную $wp_query
(на которую пользовательский объект WP_Query
не влияет) и переменную $post
(которую он может изменять, как описано выше). wp_reset_postdata()
восстанавливает только $post
, чего обычно достаточно.

Привет @janoChen:
Короткий ответ: нет.
Далее приведён PHP-код функции wp_reset_query()
из файла /wp-includes/query.php
в WordPress v3.0.4, а также функции, которые она вызывает. Как видите, в основном она работает с изменением глобальных переменных.
Когда вы используете new WP_Query($args)
, возвращаемые значения присваиваются локальной переменной. Поэтому, если вы не делаете что-то настолько сложное, что уже знали бы ответ на этот вопрос, то нет — вам не нужно вызывать wp_reset_query()
:
function wp_reset_query() {
unset($GLOBALS['wp_query']);
$GLOBALS['wp_query'] =& $GLOBALS['wp_the_query'];
wp_reset_postdata();
}
function wp_reset_postdata() {
global $wp_query;
if ( !empty($wp_query->post) ) {
$GLOBALS['post'] = $wp_query->post;
setup_postdata($wp_query->post);
}
}
function setup_postdata($post) {
global $id, $authordata, $day, $currentmonth, $page, $pages, $multipage, $more, $numpages;
$id = (int) $post->ID;
$authordata = get_userdata($post->post_author);
$day = mysql2date('d.m.y', $post->post_date, false);
$currentmonth = mysql2date('m', $post->post_date, false);
$numpages = 1;
$page = get_query_var('page');
if ( !$page )
$page = 1;
if ( is_single() || is_page() || is_feed() )
$more = 1;
$content = $post->post_content;
if ( strpos( $content, '<!--nextpage-->' ) ) {
if ( $page > 1 )
$more = 1;
$multipage = 1;
$content = str_replace("\n<!--nextpage-->\n", '<!--nextpage-->', $content);
$content = str_replace("\n<!--nextpage-->", '<!--nextpage-->', $content);
$content = str_replace("<!--nextpage-->\n", '<!--nextpage-->', $content);
$pages = explode('<!--nextpage-->', $content);
$numpages = count($pages);
} else {
$pages = array( $post->post_content );
$multipage = 0;
}
do_action_ref_array('the_post', array(&$post));
return true;
}
-Mike

@janoChen - хех. Он определенно подгоняет меня в последнее время, это точно! Наверное, как говорится, конкуренция улучшает породу (но уж точно не дает мне сделать что-то еще полезное! '-)

Просто для других читателей, так как это все еще принятый ответ (ответ @Rarst должен быть принятым). Поскольку автор вопроса использует the_post()
в своем коде, лучшие практики диктуют, что он должен использовать wp_reset_postdata()
. wp_reset_query()
вызывает wp_reset_postdata()
, так что это сработает, хотя другая вещь, которую делает wp_reset_query()
- сброс глобальной переменной $wp_query
- в данном случае не обязательна, но и не вредна. Так что ответ на самом деле ДА

Нет. Если вы создаете собственный объект WP_Query
, то он полностью в вашем распоряжении. Однако если вы вмешиваетесь в глобальную переменную global $wp_query
, то оказываетесь в глобальном пространстве имен, влияя на любой скрипт, который одновременно использует эту переменную. И если вы изменяете данные в ней, вы также должны сбросить её после завершения работы с ней.

Если вы используете пользовательский запрос, например такой:
$cat = new WP_query();
$cat->query("cat=19,20,-23&showposts=5&orderby=rand");
while ($cat->have_posts()) : $cat->the_post();
$data = get_post_meta( $post->ID, 'key', true );
$img_arrays []= $data['productimage'];
$lnk_arrays[] =get_permalink($post_ID);
endwhile;
wp_reset_query();
Тогда у вас не возникнет проблем. В противном случае, если на той же странице есть другой цикл, вы обязательно получите неожиданные результаты. Я не использовал wp_reset_query() в этом коде (который был размещен в моем файле header.php). Затем, когда я переходил в single.php, чаще всего я получал страницы деталей других категорий, что было очень неприятно. Позже я понял, что забыл сбросить запрос в начале. После этого всё заработало как надо.
