WP_Query - filtrare o direttamente?
Il numero dei miei file, template, script, query ecc. sta diventando elevato e ho bisogno di un buon sistema per gestire tutto.
Ho cercato di mantenere tutto organizzato:
- Nessun tag
<script>
nei template - CSS inline solo quando si tratta di variabili
PHP
che possono essere modificate dinamicamente dalle opzioni di amministrazione - File unici grandi per
JS
eCSS
per minimizzare le richieste
Ora è il momento di organizzare le mie query perché ne ho almeno 10 e continuano ad aumentare.
Prima opzione: usare
add_filter()
personalizzato per ogni query- Non devo cercare le query perché sono tutte in un unico file o directory
- Se devo modificarla, devo farlo solo in un posto, non in tutti i diversi template
Seconda opzione: scrivere tutte le query direttamente nei template come si fa di solito
- Praticamente ogni punto è il contrario della prima opzione
Domanda:
L'uso di filtri per gli argomenti delle query ha degli svantaggi? Prestazioni? Altro?
Esempio:
Modalità usuale:
$args = array( 'post_type' => 'my-post', 'posts_per_page' => 8, 'orderby' => 'rand', ); } $results = new WP_Query( $args );
Con filtro:
//In un file -> facile da trovare e modificare add_filter( 'some_args', 'some_search_args' ); function some_search_args( $search_args ) { $search_args['post_type'] = 'property'; $search_args['posts_per_page'] = 8; $search_args['orderby'] = 'rand'; //Tutti i tipi di logica e codice condizionale qui return $search_args; } //E //Basta includere così in qualsiasi template e tutte le volte che vuoi //Per modificare la query, basterà cambiare il codice sopra $search_args = array(); $search_args = apply_filters( 'some_args', $search_args ); $results = new WP_Query( $search_args );
Devi considerare diverse cose qui e sembra che tu sia interessato a migliorare le prestazioni di una query. La prima e più importante domanda che devi porti è:
Ho bisogno di una query personalizzata?
Ho scritto un post approfondito su questo argomento tempo fa che dovresti consultare. Se dopo aver letto il mio post nel link hai risposto sì alla domanda precedente, allora devi considerare quanto segue quando crei query personalizzate:
Evita (quando possibile) operazioni complesse di
orderby
come l'ordinamento per valori meta. SQL non è il migliore nell'ordinamento e PHP a volte è più veloce. Preferiscousort()
per ordinamenti complessi per risparmiare risorse. Anche l'ordinamento casuale è molto dispendioso in termini di risorse.Evita (quando possibile) di costruire query complesse con meta query e tax query pesantemente annidate, specialmente con molti operatori
OR
. Queste sono piuttosto impegnative per le risorse.Evita (quando possibile) di utilizzare operatori
LIKE
nel tuo SQL generato. Anche questi sono costosi.Usa i transienti (e le cache) per memorizzare query costose. Per query casuali, non puoi farlo, quindi dovrai esaminare altri metodi per affrontare questo problema.
Evita sempre il tipico ciclo
foreach
in cui ottieni un elenco di termini e poi esegui una query personalizzata per ogni singolo termine, sono davvero costosi. Piuttosto, interroga tutti i post una volta sola e poi usausort()
per ordinare i risultati.Crea una query in base a ciò che ti serve. La maggior parte delle volte abbiamo solo bisogno di interrogare i post per ottenere i loro ID da passare a un'altra funzione. In casi come questi, interroga solo gli ID dei post. Questo fa davvero risparmiare molte risorse. Basta aggiungere
'fields'=>'ids',
ai tuoi argomenti della query.Per velocizzare query non paginate, usa
get_posts()
o semplicemente passa'no_found_rows'=>true
aWP_Query
(questo è esattamente ciò che fa `get_posts). Questo salta il processo di paginazione e fa risparmiare molte risorse su database grandi.
Questo è solo inteso come una sorta di linea guida per velocizzare la query. Ci sono ancora altre cose per velocizzare le query.
L'uso di filtri per gli argomenti della query ha degli svantaggi? Prestazioni? Qualcos'altro?
Non vedo perché potrebbero esserci problemi. Se stai creando un tema commerciale, lo stai facendo sicuramente nel modo giusto. Rendere qualcosa filtrabile rende la vita molto più facile agli autori di child theme. Potrebbe costare un millesimo di millesimo di millesimo di secondo, ma è sicuramente tempo ben speso. È come la sanificazione. La sanificazione costa tempo e risorse (sebbene sia molto, molto poco), ma spendere un millisecondo in più su qualcosa può salvare il tuo sito dall'essere hackerato e distrutto.
IMHO, dovresti esaminare altri modi per velocizzare una query senza compromettere usabilità e manutenibilità. L'opzione 2 è sicuramente qualcosa che dovresti fare per temi commerciali.
IDEA (Potrebbe essere un po' eccessiva ;-))
Puoi anche usare pre_get_posts
per filtrare la tua query personalizzata e renderla filtrabile. È semplice come impostare il tuo parametro personalizzato nella tua query e poi usare quel parametro per indirizzare la tua query.
Nel seguente esempio, useremo un parametro personalizzato query_no
a cui assegneremo valori numerici.
Le Query
$q1 = new WP_Query( ['query_no' => 1] );
$q2 = new WP_Query( ['query_no' => 2] );
$q3 = new WP_Query( ['query_no' => 3] );
pre_get_posts
add_action( 'pre_get_posts', function( $q )
{
if ( $q->get( 'query_no' ) == 1 ) {
$q->set( 'posts_per_page', -1 );
// Aggiungi qualsiasi altro argomento extra da impostare
}
if ( $q->get( 'query_no' ) == 2 ) {
$q->set( 'post_type', ['post', 'page'] );
// Aggiungi qualsiasi altro argomento extra da impostare
}
if ( $q->get( 'query_no' ) == 3 ) {
$q->set( 'post_status', 'trash' );
// Aggiungi qualsiasi altro argomento extra da impostare
}
} );
L'utente ora può aggiungere argomenti aggiuntivi o modificare quelli passati.
add_action( 'pre_get_posts', function( $q )
{
if ( $q->get( 'query_no' ) == 2 ) {
// Aggiungiamo un altro post type
$post_types = $q->get( 'post_type' );
$post_types = array_merge( $post_types, ['my_post_type'] );
$q->set( 'post_type' , $post_types );
$q->set( 'posts_per_page', -1 );
// Aggiungi qualsiasi altro argomento extra da impostare
}
},
11 // Assicurati che questo venga eseguito dopo l'azione predefinita
);

Cosa ne pensi dei transient quando i risultati delle query sono gli stessi? Esempio banale ma comunque: la query viene fatta via ajax ->
imposta un transient ->
e quando l'utente spamma il bottone senza cambiare i campi di input (ho impostato una protezione anti-spam per i pulsanti ajax ma comunque..) ->
ottieni i risultati dai transient? Lo chiedo perché la mia query enorme è legata a una mappa e lo zoom/panning richiama un'altra query esattamente identica perché mostrare es. 100 000 marcatori uccide ogni browser.

Dai un'occhiata ai post collegati sotto usort()
. Io creo nomi di transient unici prendendo gli argomenti, poi uso md5()
per creare una chiave unica da aggiungere al nome del transient. In questo modo, se gli argomenti della query cambiano, viene creato un transient unico. Qualsiasi altra chiamata successiva con gli stessi argomenti semplicemente carica i risultati dal transient.

Scusa, devo essere cieco perché non l'avevo visto prima.. Grazie per la risposta molto dettagliata.
