Нужно ли использовать wp_reset_query() при вызове WP_Query в WordPress?

29 янв. 2011 г., 08:52:50
Просмотры: 17.1K
Голосов: 28

Я использую следующий код для получения записей:

<?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()? Если да, то где его следует разместить?

2
Комментарии

Похожий вопрос: Когда использовать WP_Query, query_posts() или get_posts()?

Jan Fabry Jan Fabry
29 янв. 2011 г. 11:40:30

Если вы где-то ещё на странице полагаетесь на объект основного запроса, тогда Да! вам следует вызвать его, чтобы убедиться, что объект основного запроса содержит данные, которые были до итерации вашего пользовательского запроса. Когда вы вызываете метод the_post() (например, $my_custom_query->the_post()), вы перезаписываете переменные постов, которые использует основной запрос, а сброс возвращает эти переменные к предыдущим данным при его вызове. Хорошей практикой является использование сброса после пользовательских запросов.

t31os t31os
29 янв. 2011 г. 14:32:02
Все ответы на вопрос 4
0
22

Для самого WP_Query это не обязательно, но необходимо (или, по крайней мере, является хорошей практикой), если вы используете связанные функции/методы (такие как the_post() или setup_postdata()), чтобы заполнить глобальные переменные вашими данными.

По сути, создание нового объекта WP_Query — это просто извлечение данных, но использование его для запуска активного цикла и предоставления доступа к данным для тегов шаблонов изменяет окружение, поэтому хорошо сбросить всё обратно после завершения.

В целом — вызов этой функции не создаёт значительных накладных расходов, поэтому проще всегда вызывать её, чем решать, нужно ли это делать, или забыть о ней и столкнуться с загадочными ошибками.

Обновление

Функция wp_reset_postdata() кажется более подходящим выбором. wp_reset_query() сбрасывает глобальную переменную $wp_query (на которую пользовательский объект WP_Query не влияет) и переменную $post (которую он может изменять, как описано выше). wp_reset_postdata() восстанавливает только $post, чего обычно достаточно.

29 янв. 2011 г. 15:50:33
2
10

Привет @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

29 янв. 2011 г. 08:55:16
Комментарии

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

MikeSchinkel MikeSchinkel
29 янв. 2011 г. 09:20:17

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

Tom Auger Tom Auger
22 июл. 2013 г. 22:22:21
0

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

13 июл. 2013 г. 19:54:07
0

Если вы используете пользовательский запрос, например такой:

$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, чаще всего я получал страницы деталей других категорий, что было очень неприятно. Позже я понял, что забыл сбросить запрос в начале. После этого всё заработало как надо.

16 июн. 2011 г. 13:19:13