Quando dovresti usare WP_Query rispetto a query_posts() e get_posts()? - Guida WordPress

13 set 2010, 15:58:39
Visualizzazioni: 197K
Voti: 465

Sembra che metà dei tutorial nel Codex e nel blogosphere utilizzino query_posts() e l'altra metà usi WP_Query.

Tutti fanno cose simili, quindi quando dovrei usare uno piuttosto che gli altri?

1
Commenti

Consulta anche questa analisi più approfondita

prosti prosti
25 dic 2016 23:26:16
Tutte le risposte alla domanda 7
22
748
  • query_posts() è eccessivamente semplicistico e un modo problematico per modificare la query principale di una pagina sostituendola con una nuova istanza della query. È inefficiente (ri-esegue le query SQL) e in alcuni casi fallirà completamente (spesso quando si ha a che fare con l'impaginazione dei post). Qualsiasi codice WP moderno dovrebbe utilizzare metodi più affidabili, come sfruttare l'hook pre_get_posts, per questo scopo. TL;DR non usare mai query_posts().

  • get_posts() è molto simile nell'utilizzo e accetta gli stessi argomenti (con alcune differenze, come valori predefiniti diversi), ma restituisce un array di post, non modifica le variabili globali ed è sicuro da usare ovunque.

  • WP_Query è la classe che gestisce entrambi dietro le quinte, ma puoi anche creare e lavorare con la tua istanza personalizzata. Un po' più complesso, meno restrizioni, anch'esso sicuro da usare ovunque.

Diagramma WP_Query vs query_posts vs get_posts Fonte immagine: https://www.rarst.net/images/query_functions.png

13 set 2010 16:10:20
Commenti

(1) "ed è sicuro da usare ovunque" --> ma non usarlo per il loop PRINCIPALE. (2) ricorda di usare global $query_string; prima della riga che contiene query_posts();

edelwater edelwater
19 feb 2011 10:05:19

@scribu d'altra parte 'get_posts' funzionerà anche se non consigliato: http://core.trac.wordpress.org/ticket/16545

edelwater edelwater
19 feb 2011 10:27:18

Credo che query_posts sia anche meno efficiente in quanto eseguirà query aggiuntive, mentre se usi solo WP_Query per il tuo loop principale, eseguirà solamente la query che hai scelto in WP_Query.

jjeaton jjeaton
8 ago 2011 14:15:09

@jjeaton query_posts() è una piccola funzione wrapper per WP_Query, l'unica cosa extra che fa (come per il diagramma di flusso) è sovrascrivere la variabile globale $wp_query

Rarst Rarst
8 ago 2011 15:39:23

@Rarst Mi riferivo a questa sezione nel Codex per query_posts tuttavia, potrei essermi sbagliato riguardo all'effetto sulle prestazioni. A meno che usare WP_Query nel tuo file template non abbia lo stesso risultato (cioè scartare la tua query e rieseguirla)

jjeaton jjeaton
8 ago 2011 16:33:13

@jjeaton Sostituire query_posts() con WP_Query non farà alcuna differenza nelle prestazioni, la query originale della pagina verrà comunque eseguita perché fa parte del caricamento del core. Quelle query verranno eseguite anche se il tuo file template non ha alcun loop.

Rarst Rarst
8 ago 2011 17:15:17

Non riesco a liberarmi dalla sensazione che questo sia il post più geniale e votato su WPSE. Dovrebbe essere anche nel Codex.

kaiser kaiser
16 set 2011 00:03:07

Ok, dopo averlo guardato per più di un bel po' di tempo, penso che a query_posts() manchi una variabile statica che viene impostata su true dopo il primo uso e - se usata due volte - dovrebbe attivare _doing_it_wrong();. Credo che segnalerò questa cosa ai ragazzi di wp-hacker o trac.

kaiser kaiser
16 set 2011 00:06:12

@kaiser beh... usare query_posts() due volte è più o meno dannoso come usarla una volta, non fa molta differenza secondo me. :) comunque Andrew Nacin farà una presentazione sulle query e ha detto che potrebbe proporre alcuni miglioramenti al diagramma di flusso, quindi una versione due potrebbe arrivare in futuro.

Rarst Rarst
16 set 2011 09:41:04

Aggiungerò la mia descrizione più chiara del problema della "performance di query_posts()": Usare query_posts() o WP_Query all'interno di un file template avrà lo stesso costo in termini di performance: la query che hai appena eseguito. Il problema discusso nell'articolo del codex è che se vuoi davvero sostituire la query dovresti farlo filtrando la query_posts() originale con il filtro 'parse_query'. In questo modo avrai solo la singola query originale e desiderata, piuttosto che eseguire una seconda query per sostituirla in modo scomodo. query_posts() NON È MAI LA SOLUZIONE!! MAI!

jerclarke jerclarke
19 apr 2012 22:24:25

Questo non menziona il filtro 'request', che è un ottimo modo per modificare la query principale. Il vantaggio rispetto a query_posts è che questa funzione cancella la query originale e ne genera una nuova - esattamente come se usassi WP_Query. Usando il filtro request, stai modificando la query originale prima che venga mai inviata. Penso che sia questo ciò a cui si riferisce @JeremyClarke sopra.

eddiemoya eddiemoya
2 mag 2012 19:32:59

C'è una spiegazione fantastica di query_posts scritta da John James Jacoby sul blog developer.wordpress.com che supera tutte queste risposte. Il punto principale: query_posts non modifica affatto il main loop, lo sostituisce dopo che è già stato eseguito. Il modo migliore per modificare il main loop è attraverso un filtro pre_get_posts.

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

Dan Gayle Dan Gayle
9 giu 2012 23:10:48

@Dan stai confondendo l'implementazione tecnica e lo scopo. query_posts() sostituisce l'oggetto del loop principale, ma il suo scopo è modificare il loop principale. Inoltre ho una grande simpatia per i filtri del loop, ma non era questo che chiedeva la domanda. C'è una domanda di follow-up da parte di un'altra persona su quel tema.

Rarst Rarst
10 giu 2012 10:44:50

La domanda era "Quando dovresti usare... query_posts()" e secondo la logica presentata da quel post del blog e dai commenti sopra, la risposta è probabilmente mai.

Dan Gayle Dan Gayle
11 giu 2012 20:04:17

quindi, se è così male, perché esiste query_posts?

Manny Fleurmond Manny Fleurmond
10 set 2012 17:33:49

@Manny Fleurmond concettualmente query_posts() è un tentativo di semplificare i concetti del main loop al livello di un template tag (la facilità è uno dei punti forti della popolarità di WP). Il compito si è rivelato semplicemente troppo complesso per un template tag. Gli sviluppatori core hanno accennato alla possibilità di deprecarlo, ma non credo sia stata ancora presa una decisione al riguardo.

Rarst Rarst
10 set 2012 18:04:30

In realtà non puoi usare WP_Query() "ovunque", ho appena provato e va ancora in crash con $thequery->have_posts(), ricorsione infinita, vedi http://wordpress.stackexchange.com/questions/34270

NoBugs NoBugs
21 ott 2014 07:16:37

@NoBugs il loop in quella domanda è sbagliato e c'è una risposta che spiega il perché.

Rarst Rarst
21 ott 2014 07:54:12

Ahhh grazie per questo. Finalmente qualcosa che ha senso. Seriamente, WordPress e la loro pessima documentazione. Non so come un software così contorto e con standard di codifica scadenti sia diventato così popolare.

racl101 racl101
16 apr 2015 23:32:31

Ho trovato questo test di velocità tra wp_query e get_posts http://www.wpclocked.com/

Anagio Anagio
18 lug 2015 20:36:53

Mi fiderei di un test del genere... esattamente zero. :) La funzione è un wrapper molto leggero, qualsiasi differenza deriverebbe da lievi differenze negli argomenti e/o negli hook.

Rarst Rarst
19 lug 2015 16:50:45

Nessuna necessità di emozioni, query_posts() è una funzione con effetti collaterali: imposta una variabile globale. WordPress è pieno di funzioni con effetti collaterali. Questo non è un problema di prestazioni ma un problema di qualità del codice. Guarda https://developer.wordpress.org/reference/functions/query_posts/ e vedi cosa fa query_posts. Usa WP_Query a meno che tu non voglia scombussolare le variabili globali.

th00ht th00ht
14 mar 2020 17:22:07
Mostra i restanti 17 commenti
3
96

query_posts - Non dovresti mai utilizzare query_posts. Oltre a quanto detto da @Rarst, il problema più grande con query_posts è che rompe l'oggetto della query principale (memorizzato in $wp_query). Molti plugin e codice personalizzato si basano sull'oggetto della query principale, quindi rompere l'oggetto della query principale significa che stai rompendo le funzionalità dei plugin e del codice personalizzato. Una di queste funzioni è l'importante funzione di paginazione, quindi se rompi la query principale, rompi la paginazione.

Per dimostrare quanto sia dannoso query_posts, in qualsiasi template, esegui il seguente codice e confronta i risultati

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

get_posts e WP_Query sono il modo corretto per costruire query secondarie ( come post correlati, slider, contenuti in evidenza e contenuti su pagine frontali statiche ). È importante notare che non dovresti utilizzare nessuno dei due al posto della query principale nella home page, nella pagina singola o in qualsiasi tipo di pagina di archivio, poiché romperà la funzionalità della pagina. Se devi modificare la query principale, usa pre_get_posts per farlo, e non una query personalizzata. (AGGIORNAMENTO: Per le pagine frontali statiche e le pagine vere, vedi Usare pre_get_posts su pagine vere e pagine frontali statiche*)

In sostanza, WP_Query è utilizzato dalla query principale ed è anche utilizzato da get_posts, ma sebbene get_posts() utilizzi WP_Query, ci sono alcune differenze

  • get_posts è più veloce di WP_Query. Il margine dipende dalla quantità totale di post del sito. Il motivo è che get_posts passa 'no_found_rows' => true di default a WP_Query, il quale salta/rompe legalmente la paginazione. Con 'no_found_rows' => true, WP_Query ottiene il numero di post richiesti, poi interrompe, mentre di default cerca ulteriormente tutti i post corrispondenti alla query per calcolare la paginazione.

    Per questo motivo, get_posts() dovrebbe essere utilizzato solo per query non paginate. Paginare get_posts è davvero un grosso pasticcio. WP_Query dovrebbe essere utilizzato per tutte le query paginate

  • get_posts() non è influenzato dai filtri posts_* mentre WP_Query ne è influenzato. Il motivo è che get_posts, di default, passa 'suppress_filters' => true a WP_Query

  • get_posts ha alcuni parametri extra come include, exclude, numberposts e category. Questi parametri vengono convertiti in parametri validi per WP_Query prima di essere passati a WP_Query. include viene convertito in post__in, exclude in post__not_in, category in cat e numberposts in posts_per_page. Solo una nota, tutti i parametri che possono essere passati a WP_Query funzionano con get_posts, puoi ignorare e non utilizzare i parametri di default di get_posts

  • get_posts restituisce solo la proprietà $posts di WP_Query mentre WP_Query restituisce l'oggetto completo. Questo oggetto è molto utile quando si tratta di condizionali, paginazione e altre informazioni utili che possono essere utilizzate all'interno del loop.

  • get_posts non utilizza il loop, ma un ciclo foreach per visualizzare i post. Inoltre, nessun template tag è disponibile di default. setup_postdata( $post ) deve essere utilizzato per rendere disponibili i template tag. WP_Query utilizza il loop e i template tag sono disponibili di default

  • get_posts passa 'ignore_sticky_posts' => 1 a WP_Query, quindi get_posts di default ignora i post sticky

In base a quanto sopra, se utilizzare get_posts o WP_Query dipende da te e da ciò di cui hai effettivamente bisogno dalla query. Quanto sopra dovrebbe guidarti nella tua scelta

18 giu 2015 17:46:01
Commenti

Vorrei poter mettere tra i preferiti le risposte. Questo spiega così tanto.

InanisAtheos InanisAtheos
12 giu 2017 07:17:52

Ottima spiegazione!

"get_posts() dovrebbe essere usato solo per query non paginate. Paginare get_posts è davvero un grande casino. WP_Query dovrebbe essere usato per tutte le query paginate" è fondamentalmente tutto ciò che qualcuno ha bisogno di sapere secondo me.

Bullyen Bullyen
19 apr 2018 19:27:06

@pieter-goosen, sai se lo stesso vale per WP User Query rispetto a get_users? Mi riferisco alla parte sulle prestazioni.

User User
5 ago 2021 06:34:29
0
35

La differenza fondamentale è che query_posts() è utile solo per modificare il Loop corrente. Una volta terminato, è necessario ripristinare il loop e lasciarlo proseguire. Questo metodo è anche un po' più semplice da comprendere, principalmente perché la tua "query" è sostanzialmente una stringa URL che passi alla funzione, in questo modo:

query_posts('meta_key=colore&meta_value=blu'); 

D'altra parte, WP_Query è uno strumento più generico e somiglia più alla scrittura diretta di query MySQL rispetto a query_posts(). Puoi usarlo ovunque (non solo nel Loop) e non interferisce con le query di articoli attualmente in esecuzione.

Personalmente, tendo a usare WP_Query più spesso. In definitiva, la scelta dipenderà dal tuo caso specifico.

13 set 2010 16:09:13
0
17

Non c'è assolutamente bisogno di utilizzare query_posts(). Tutto ciò che fa è istanziare un nuovo oggetto WP_Query e riassegnare quel nuovo oggetto a global wp_query.

Per riferimento, la seguente è la funzione effettiva di query_posts().

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

Istanzia il tuo oggetto WP_Query se vuoi creare uno script di query personalizzato avanzato. Oppure usa get_posts() se tutto ciò che devi fare è qualche leggera modifica qua e là.

In ogni caso, ti consiglio vivamente di farti un favore e andare in wp_includes/query.php e esaminare la classe WP_Query.

13 lug 2013 16:38:02
0
16

Assicurati di utilizzare wp_reset_query() dopo aver usato query_posts() perché influenzerà anche i risultati di altre query.

8 lug 2013 04:50:45
0
12

Se ricordo bene ciò che ho letto, essenzialmente "il loop" esegue WP_Query nei file core, ma in un modo più semplice da comprendere.

23 set 2010 20:21:34
0
  • query_posts(): potrebbe essere utilizzato in un unico caso se è necessario modificare la query principale. Imposta molte variabili globali;
  • get_posts(): è molto simile nel funzionamento e accetta gli stessi argomenti, ma restituisce un array di post
  • WP_Query: puoi creare e lavorare con un tuo oggetto di questa classe. Un po' più complesso, meno restrizioni, è sicuro da usare ovunque.
19 lug 2017 14:28:38