Când să folosești WP_Query vs query_posts() vs get_posts() în WordPress?

13 sept. 2010, 15:58:39
Vizualizări: 197K
Voturi: 465

Se pare că jumătate din tutorialele din Codex și de pe bloguri folosesc query_posts(), iar cealaltă jumătate folosește WP_Query.

Toate fac lucruri similare, așa că când ar trebui să folosesc una în locul celorlalte?

1
Comentarii

Verifică și această analiză mai amplă

prosti prosti
25 dec. 2016 23:26:16
Toate răspunsurile la întrebare 7
22
748
  • query_posts() este o metodă prea simplistă și problematică de a modifica interogarea principală a unei pagini prin înlocuirea ei cu o nouă instanță a interogării. Este ineficientă (re-execută interogările SQL) și va eșua în anumite circumstanțe (mai ales când vine vorba de paginarea postărilor). Orice cod WP modern ar trebui să utilizeze metode mai fiabile, cum ar fi folosirea hook-ului pre_get_posts, în acest scop. TL;DR nu folosiți niciodată query_posts().

  • get_posts() este foarte similar în utilizare și acceptă aceleași argumente (cu unele nuanțe, cum ar fi valorile implicite diferite), dar returnează un array de postări, nu modifică variabilele globale și este sigur de utilizat oriunde.

  • WP_Query este clasa care stă la baza ambelor funcții, dar puteți crea și lucra cu propria instanță a acesteia. Un pic mai complexă, mai puține restricții, de asemenea sigură de utilizat oriunde.

Diagramă comparativă WP_Query vs query_posts vs get_posts Sursa imaginii: https://www.rarst.net/images/query_functions.png

13 sept. 2010 16:10:20
Comentarii

(1) "și este sigur de utilizat oriunde" --> dar nu utilizați aceasta pentru bucla PRINCIPALĂ. (2) nu uitați să folosiți global $query_string; înaintea liniei care conține query_posts();

edelwater edelwater
19 feb. 2011 10:05:19

@scribu din nou 'get_posts' va funcționa deși nu este recomandat: http://core.trac.wordpress.org/ticket/16545

edelwater edelwater
19 feb. 2011 10:27:18

Cred că query_posts este de asemenea mai puțin eficient deoarece va rula interogări suplimentare, în timp ce dacă utilizați doar WP_Query pentru bucla principală, va rula doar interogarea pe care o alegeți în WP_Query.

jjeaton jjeaton
8 aug. 2011 14:15:09

@jjeaton query_posts() este o mică funcție wrapper pentru WP_Query, singurul lucru suplimentar pe care îl face (conform diagramei) este suprascrierea variabilei globale $wp_query

Rarst Rarst
8 aug. 2011 15:39:23

@Rarst Mă refeream la această secțiune din Codex pentru query_posts, totuși, este posibil să greșesc în legătură cu efectul asupra performanței. Cu excepția cazului în care utilizarea WP_Query în fișierul template va avea același rezultat (adică renunțarea la interogarea ta și reexecutarea ei)

jjeaton jjeaton
8 aug. 2011 16:33:13

@jjeaton Înlocuirea query_posts() cu WP_Query nu va face nicio diferență în performanță, interogarea originală a paginii va rula în continuare deoarece aceasta face parte din încărcarea de bază. Aceste interogări vor rula chiar dacă fișierul tău template nu conține deloc buclă.

Rarst Rarst
8 aug. 2011 17:15:17

Nu pot scăpa de sentimentul că acesta este cel mai genial și apreciat post de pe WPSE. Ar trebui să fie și în Codex.

kaiser kaiser
16 sept. 2011 00:03:07

Ok, după ce m-am uitat la el mai mult decât destul de mult, cred că query_posts() îi lipsește o variabilă statică care să fie setată pe true după prima utilizare și - dacă este folosită de două ori - ar trebui să declanșeze _doing_it_wrong();. Cred că o să deranjez tipii de la wp-hacker sau trac cu asta.

kaiser kaiser
16 sept. 2011 00:06:12

@kaiser ei bine... folosirea query_posts() de două ori este la fel de rea ca o dată, nu contează prea mult pentru mine. :) apropo, Andrew Nacin va ține o prezentare despre interogări și a spus că ar putea propune unele îmbunătățiri la organigramă, așa că versiunea a doua ar putea veni în viitorul apropiat.

Rarst Rarst
16 sept. 2011 09:41:04

Voi adăuga cea mai clară descriere a problemei "performanței lui query_posts()": Folosirea query_posts() sau WP_Query într-un fișier de șablon va avea același cost de performanță: interogarea pe care tocmai ai efectuat-o. Problema discutată în articolul codex este că dacă chiar vrei să înlocuiești interogarea, ar trebui să o faci prin filtrarea query_posts() original cu filtrul 'parse_query'. În acest fel vei avea doar o singură interogare originală și dorită, în loc să faci o a doua interogare pentru a o înlocui stânjenitor. query_posts() NU ESTE NICIODATĂ SOLUȚIA!! NICIODATĂ!

jerclarke jerclarke
19 apr. 2012 22:24:25

Acest lucru nu menționează filtrul 'request', care este o modalitate excelentă de a modifica interogarea principală. Avantajul față de query_posts este că acea funcție șterge interogarea originală și generează una nouă - la fel ca și cum ai folosi WP_Query. Prin utilizarea filtrului request, modifici interogarea originală înainte ca aceasta să fie trimisă. Cred că la asta se referă @JeremyClarke mai sus.

eddiemoya eddiemoya
2 mai 2012 19:32:59

Există o explicație extrem de bună despre query_posts scrisă de John James Jacoby pe blogul developer.wordpress.com care depășește toate aceste răspunsuri. Ideea principală: query_posts nu modifică bucla principală deloc, ci o înlocuiește după ce aceasta a rulat deja. Cea mai bună metodă de a modifica bucla principală este prin intermediul unui filtru pre_get_posts.

http://developer.wordpress.com/2012/05/14/querying-posts-without-query_posts/

Dan Gayle Dan Gayle
9 iun. 2012 23:10:48

@Dan confunzi implementarea tehnică cu scopul. query_posts() înlocuiește într-adevăr obiectul loop-ului principal, dar scopul său este de a modifica loop-ul principal. De asemenea, sunt un mare adept al filtrelor de loop, dar întrebarea nu era despre asta. Există o întrebare de follow-up de la altcineva pe această temă.

Rarst Rarst
10 iun. 2012 10:44:50

Întrebarea era "Când ar trebui să folosești... query_posts()" și conform logicii prezentate în acel articol de blog și comentariile de mai sus, răspunsul este probabil niciodată.

Dan Gayle Dan Gayle
11 iun. 2012 20:04:17

deci, dacă e atât de rău, de ce există query_posts?

Manny Fleurmond Manny Fleurmond
10 sept. 2012 17:33:49

@Manny Fleurmond conceptual, query_posts() este o încercare de a simplifica conceptele de buclă principală la nivelul unui tag de șablon de temă (ușurința fiind unul dintre punctele forte pentru popularitatea WP). Sarcina s-a dovedit pur și simplu prea complexă pentru ca un tag de șablon să o poată realiza. Dezvoltatorii de bază au exprimat posibilitatea ca aceasta să fie depreciată, dar nu cred că s-a luat încă o decizie în acest sens.

Rarst Rarst
10 sept. 2012 18:04:30

De fapt, nu poți „folosi oriunde” WP_Query(), tocmai am încercat și încă dă eroare la $thequery->have_posts(), recursivitate infinită, vezi http://wordpress.stackexchange.com/questions/34270

NoBugs NoBugs
21 oct. 2014 07:16:37

@NoBugs bucla din acea întrebare este greșită și există un răspuns care explică de ce.

Rarst Rarst
21 oct. 2014 07:54:12

Agghh mulțumesc pentru asta. În sfârșit, ceva care are sens. Serios, WordPress și documentația lor proastă. Nu știu cum un software atât de încâlcit și standarde de codare proaste au devenit atât de populare.

racl101 racl101
16 apr. 2015 23:32:31

Am găsit acest test de viteză între wp_query și get_posts http://www.wpclocked.com/

Anagio Anagio
18 iul. 2015 20:36:53

Aș avea încredere într-un astfel de test... exact zero. :) Funcția este un înveliș foarte subțire, orice diferență va veni din mici diferențe în argumente și/sau hook-uri.

Rarst Rarst
19 iul. 2015 16:50:45

Nu este nevoie de emoții, query_posts() este o funcție cu efecte secundare: setează o variabilă globală. WordPress este plin de funcții cu efecte secundare. Aceasta nu este o problemă de performanță, ci o problemă de calitate a codului. Verifică https://developer.wordpress.org/reference/functions/query_posts/ și vezi ce face query_posts. Folosește WP_Query dacă nu vrei să încurci variabilele globale.

th00ht th00ht
14 mar. 2020 17:22:07
Arată celelalte 17 comentarii
3
96

query_posts - Nu ar trebui să folosești niciodată query_posts. Pe lângă ceea ce a menționat @Rarst, cea mai mare problemă cu query_posts este că distruge obiectul principal al interogării (stocat în $wp_query). Multe plugin-uri și cod personal se bazează pe obiectul principal al interogării, așa că distrugerea acestuia înseamnă că strici funcționalitățile plugin-urilor și ale codului personal. Doar una dintre aceste funcții este funcția extrem de importantă de paginare, deci dacă strici interogarea principală, strici paginarea.

Pentru a demonstra cât de rău este query_posts, pe orice șablon, fă următoarele și compară rezultatele

var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );

get_posts și WP_Query sunt metodele corecte pentru a construi interogări secundare ( precum postări înrudite, slide-uri, conținut recomandat și conținut pe pagini frontale statice ). Trebuie menționat că nu ar trebui să folosești niciuna dintre acestea în locul interogării principale pe pagina de start, pagina single sau orice tip de pagină de arhivă, deoarece va afecta funcționalitatea paginii. Dacă trebuie să modifici interogarea principală, folosește pre_get_posts pentru a face acest lucru, și nu o interogare personalizată. (ACTUALIZARE: Pentru paginile frontale statice și paginile adevărate, vezi Folosirea pre_get_posts pe pagini adevărate și pagini frontale statice*)

În esență, WP_Query este folosit de interogarea principală și este folosit și de get_posts, dar deși get_posts() utilizează WP_Query, există câteva diferențe:

  • get_posts este mai rapid decât WP_Query. Diferența depinde de numărul total de postări ale site-ului. Motivul pentru aceasta este că get_posts trece implicit 'no_found_rows' => true către WP_Query, ceea ce omite/întrerupe legal paginarea. Cu 'no_found_rows' => true, WP_Query obține numărul de postări interogate, apoi se oprește, în timp ce implicit, continuă să caute toate postările care corespund interogării pentru a calcula paginarea.

    Din acest motiv, get_posts() ar trebui folosit doar pentru interogări ne-paginate. Paginarea get_posts este o adevărată mizerie. WP_Query ar trebui folosit pentru toate interogările paginate.

  • get_posts() nu sunt influențate de filtrele posts_*, în timp ce WP_Query este influențat de aceste filtre. Motivul este că get_posts, implicit, trece 'suppress_filters' => true către WP_Query.

  • get_posts are câțiva parametri extra precum include, exclude, numberposts și category. Acești parametri sunt transformați în parametri valizi pentru WP_Query înainte de a fi pasați către WP_Query. include este transformat în post__in, exclude în post__not_in, category în cat și numberposts în posts_per_page. Doar o notă, toți parametrii care pot fi pasați către WP_Query funcționează și cu get_posts, poți ignora și nu folosi parametrii impliciți ai get_posts.

  • get_posts returnează doar proprietatea $posts a WP_Query, în timp ce WP_Query returnează întregul obiect. Acest obiect este foarte util când vine vorba de condiționale, paginare și alte informații utile care pot fi folosite în interiorul buclei.

  • get_posts nu folosește bucla, ci o buclă foreach pentru a afișa postările. De asemenea, niciun tag de șablon nu este disponibil implicit. setup_postdata( $post ) trebuie folosit pentru a face tag-urile de șablon disponibile. WP_Query folosește bucla și tag-urile de șablon sunt disponibile implicit.

  • get_posts trece 'ignore_sticky_posts' => 1 către WP_Query, deci get_posts ignoră implicit postările lipicioase.

Pe baza celor de mai sus, dacă să folosești get_posts sau WP_Query depinde de tine și de ce ai nevoie de fapt din interogare. Cele de mai sus ar trebui să te ghideze în alegerea ta.

18 iun. 2015 17:46:01
Comentarii

Aș dori să pot marca răspunsurile ca favorite. Asta explică atât de multe.

InanisAtheos InanisAtheos
12 iun. 2017 07:17:52

Explicație excelentă!

"get_posts() ar trebui folosit doar pentru interogări nepaginate. Paginarea get_posts este cu adevărat o mare mizerie. WP_Query ar trebui utilizat pentru toate interogările paginate" este practic tot ce trebuie să știe cineva, după părerea mea.

Bullyen Bullyen
19 apr. 2018 19:27:06

@pieter-goosen, știi dacă același lucru este valabil și pentru WP User Query în comparație cu get_users? Mă refer la partea de performanță.

User User
5 aug. 2021 06:34:29
0
35

Diferența de bază este că query_posts() este destinat doar modificării buclei curente. După ce ai terminat, este necesar să resetezi bucla și să o lași să continue. Această metodă este și puțin mai ușor de înțeles, pur și simplu pentru că "interogarea" ta este practic un șir URL pe care îl transmiți funcției, astfel:

query_posts('meta_key=color&meta_value=blue');

Pe de altă parte, WP_Query este mai mult un instrument de uz general și este mai aproape de scrierea directă a interogărilor MySQL decât query_posts(). De asemenea, îl poți folosi oriunde (nu doar în buclă) și nu interferează cu nicio interogare de postări în curs.

Personal, tind să folosesc WP_Query mai des. În realitate, totul se reduce la cazul tău specific.

13 sept. 2010 16:09:13
0
17

Nu există absolut nicio necesitate de a folosi query_posts(). Tot ce face această funcție este să instantieze un nou obiect WP_Query și să realoce acel obiect nou la global wp_query.

Pentru referință, următoarea este funcția actuală query_posts().

 function query_posts($query) {
        $GLOBALS['wp_query'] = new WP_Query();
        return $GLOBALS['wp_query']->query($query);
    }

Instanțiați-vă propriul obiect WP_Query dacă doriți să creați un script personalizat de interogare în detaliu. Sau folosiți get_posts() dacă tot ce trebuie să faceți este o ușoară manipulare aici și acolo.

În orice caz, vă recomand să vă faceți o favoare și să mergeți la wp_includes/query.php și să parcurgeți clasa WP_Query.

13 iul. 2013 16:38:02
0
16

Asigurați-vă că utilizați wp_reset_query() după ce ați folosit query_posts() deoarece va afecta și alte rezultate ale interogării.

8 iul. 2013 04:50:45
0
12

Dacă îmi amintesc corect, în esență "the loop" efectuează WP_Query în fișierele de bază, dar într-un mod mai ușor de înțeles.

23 sept. 2010 20:21:34
0
  • query_posts(): poate fi utilizat într-un singur caz și numai dacă trebuie să modifici interogarea principală. Acesta setează multe variabile globale;
  • get_posts(): este foarte similar ca mecanism și acceptă aceleași argumente, dar returnează un array de postări
  • WP_Query: poți crea și lucra cu propriul obiect al acestuia. Un pic mai complex, mai puține restricții, este sigur să-l folosești oriunde.
19 iul. 2017 14:28:38