Czy konieczne jest użycie wp_reset_query () w wywołaniu WP_Query?

26

Korzystam z następującego kodu, aby pobrać posty:

<?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">
        By <?php the_author() ?>
    </div>
    <div class="storycontent">
        <?php the_excerpt(); ?>
    </div>

<?php endwhile; ?>

Czy muszę używać wp_reset_query()? Jeśli tak, to gdzie mam to umieścić?

janoChen
źródło
2
Jeśli korzystasz z głównego obiektu zapytania gdzieś na stronie, to tak! powinieneś to nazwać, aby upewnić się, że główny obiekt zapytania zawiera dane, które zostały wykonane przed iteracją niestandardowego zapytania. Kiedy wywołujesz the_post()metodę (tj. $my_custom_query->the_post()), Uzupełniasz zmienne wpisu, na które patrzy główne zapytanie, reset wypełnia te zmienne poprzednimi danymi, kiedy je wywołujesz. Dobrą praktyką jest używanie resetowania po niestandardowych zapytaniach.
t31os

Odpowiedzi:

10

Cześć @janoChen:

Prosta odpowiedź: nie.

Poniżej znajduje się kod PHP dla funkcji wp_reset_query()z /wp-includes/query.phpWordPRess v3.0.4, a także później wywołane funkcje. Widać, że chodzi przede wszystkim o modyfikację zmiennych globalnych.

Podczas korzystania new WP_Query($args)będziesz przypisywać wartość zwracaną z wartości do zmiennej lokalnej, więc jeśli nie robisz czegoś tak skomplikowanego, że znasz już odpowiedź na to pytanie, nie, nie musisz dzwonić 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;
}

-Mikrofon

MikeSchinkel
źródło
@janoChen - heh. Zdecydowanie ostatnio mnie naciskał, to na pewno! Wydaje mi się, że, jak mówią, konkurencja poprawia rasę (ale na pewno powstrzymuje mnie przed robieniem czegoś innego produktywnego! ”-)
MikeSchinkel
1
Tylko dla innych, którzy to czytają, ponieważ wciąż jest to akceptowana odpowiedź (odpowiedź @ Rarsta powinna zostać zaakceptowana). Ponieważ OP używa the_post()w swoim kodzie, najlepsze praktyki nakazują, aby musiał z niego korzystać wp_reset_postdata(). wp_reset_query()wywołań wp_reset_postdata(), więc to zadziała, chociaż druga rzecz wp_reset_query()- resetowanie $wp_queryzmiennej globalnej - nie jest konieczne, ale w tym przypadku nie jest szkodliwe. Tak więc odpowiedź brzmi TAK
Tom Auger
21

Nie jest to konieczne WP_Querysamo w sobie, ale jest konieczne (lub przynajmniej dobre, aby zrobić), jeśli użyjesz powiązanych funkcji / metod (takich jak the_post()lub setup_postdata()), aby wypełnić zmienne globalne danymi.

Zasadniczo tworzenie nowego WP_Queryobiektu to tylko pobieranie danych, ale użycie go do uruchomienia aktywnej pętli i udostępnienie danych tagom szablonu modyfikuje środowisko i dobrze jest zresetować wszystko później.

Ogólnie rzecz biorąc - nazywanie go nie jest znaczącą utratą wydajności, więc łatwiej jest zawsze zadzwonić, niż zdecydować, czy powinieneś lub zapomnieć o tym i mieć coś tajemniczo zepsutego.

Aktualizacja

wp_reset_postdata()funkcja wydaje się bardziej odpowiednim wyborem. wp_reset_query()resetuje zmienne globalne $wp_query(które WP_Querynie wpływają na niestandardowy obiekt) i $post (które mogłyby jak wyżej) wp_reset_postdata()przywraca tylko $post, co powinno wystarczyć.

Rarst
źródło
2

Nie. Jeśli utworzysz instancję własnego obiektu WP_Query, możesz zrobić to, co chcesz. Jeśli jednak manipulujesz global $wp_queryzmienną, to w globalnej przestrzeni nazw wpływasz na skrypt każdego użytkownika, który jednocześnie używa tej zmiennej. A jeśli zrobisz coś, aby zmienić zawarte w nim dane, musisz je zresetować po zakończeniu używania.

RebelPhoenix
źródło
0

Jeśli używasz niestandardowego zapytania w ten sposób

$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(); 

Wtedy nie napotkasz problemów. W przeciwnym razie, jeśli na tej samej stronie znajduje się kolejna pętla, musisz uzyskać nieoczekiwane wyniki. Nie użyłem wp_reset_query () w powyższym kodzie (który został umieszczony w moim pliku header.php. Potem, gdy przeszedłem do single.php, głównie otrzymałem strony ze szczegółami innych kategorii, co było frustrujące. Później zdałem sobie sprawę, że zapomniałem zresetować zapytanie u góry. Wkrótce zaczęło działać jak urok.

Katie
źródło