WP_Query - filtrare sau direct?
Numărul fișierelor mele, șabloanelor, scripturilor, interogărilor etc. devine mare și am nevoie de un sistem bun pentru a le gestiona pe toate.
Am încercat să păstrez totul organizat:
- Fără tag-uri
<script>
în șabloane - CSS inline doar atunci când este vorba de o variabilă
PHP
care poate fi modificată dinamic din opțiunile de administrare - Fișiere mari unice de
JS
șiCSS
pentru a minimiza cererile etc.
Acum este momentul să-mi organizez interogările, deoarece am cel puțin 10 și numărul lor continuă să crească.
Prima opțiune: utilizarea unui filtru personalizat
add_filter()
pentru fiecare interogare- Nu trebuie să caut interogările deoarece toate se află într-un singur fișier sau director
- Dacă trebuie să o modific, trebuie să o fac într-un singur loc, nu în toate șabloanele mele diferite
A doua opțiune: scrierea tuturor interogărilor direct în șabloane așa cum se face de obicei
- Practic, fiecare punct este opusul primei opțiuni
Întrebare:
Există dezavantaje la utilizarea filtrelor pentru argumentele interogărilor? Performanță? Alte aspecte?
Exemplu:
Mod obișnuit:
$args = array( 'post_type' => 'my-post', 'posts_per_page' => 8, 'orderby' => 'rand', ); } $results = new WP_Query( $args );
Cu filtru:
//Într-un singur fișier -> ușor de găsit și modificat 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'; //Toate tipurile de logică și cod condițional pot fi adăugate aici return $search_args; } //Și //Doar includeți asta în orice șablon doriți și de câte ori doriți //Pentru a modifica interogarea, va trebui doar să modificați codul de mai sus $search_args = array(); $search_args = apply_filters( 'some_args', $search_args ); $results = new WP_Query( $search_args );
Trebuie să iei în considerare destul de multe lucruri aici și se pare că ești interesat de creșterea performanței unei interogări. Prima și cea mai importantă întrebare pe care trebuie să ți-o pui este:
Am nevoie de o interogare personalizată?
Am făcut un post extins pe acest subiect acum ceva timp, pe care ar trebui să-l verifici. Dacă ai răspuns cu "da" la întrebarea de mai sus după ce ai citit postul meu din link, atunci trebuie să iei în considerare următoarele atunci când creezi interogări personalizate:
Evită (acolo unde poți) operațiuni complexe de
orderby
, cum ar fi ordonarea după valori meta. SQL nu este cel mai bun la ordonare, iar PHP este uneori mai rapid. Preferusort()
pentru ordonări complexe pentru a economisi resurse. Ordonarea aleatorie este, de asemenea, foarte solicitantă pentru resurse.Evită (acolo unde poți) construirea de interogări complexe cu meta și tax-query-uri puternic imbricate, în special cu mulți operatori
OR
. Acestea sunt destul de dure pentru resurse.Evită (acolo unde poți) utilizarea operatorilor
LIKE
în SQL-ul generat. Aceștia sunt, de asemenea, costisitori.Folosește transiente (și cache-uri) pentru a stoca interogări costisitoare. Pentru interogări aleatorii, nu poți face acest lucru, așa că va trebui să analizezi alte metode pentru a rezolva această problemă.
Evită întotdeauna bucla tipică
foreach
în care obții o listă de termeni și apoi rulezi o interogare personalizată pentru fiecare termen, acestea sunt foarte costisitoare. Mai degrabă interoghează toate postările o singură dată și apoi foloseșteusort()
pentru a sorta rezultatele.Creează o interogare în funcție de ceea ce ai nevoie. De cele mai multe ori avem nevoie doar să interogăm postări pentru a obține ID-urile lor și să le transmitem unei alte funcții. În astfel de cazuri, interoghează doar ID-urile postărilor. Acest lucru economisește mult din resurse. Pur și simplu adaugă
'fields'=>'ids',
la argumentele interogării tale.Pentru a accelera interogările nepaginate, folosește
get_posts()
sau pur și simplu adaugă'no_found_rows'=>true
laWP_Query
(acesta este exact ceea ce face `get_posts). Acest lucru săre peste procesul de paginare și economisește multe resurse pe baze de date mari.
Acesta este menit doar ca un fel de ghid pentru a accelera interogarea. Mai sunt și alte lucruri care pot accelera interogările.
Utilizarea filtrelor pentru argumentele interogării are vreun dezavantaj? Performanță? Altceva?
Nu văd de ce ar putea fi probleme. Dacă creezi o temă comercială, faci cu siguranță lucrurile corect. Făcând ceva filtrabil, viața autorilor de teme child devine mult mai ușoară. S-ar putea să coste o milime dintr-o milisecundă, dar este cu siguranță timp bine folosit. Este ca și sanatizarea. Sanatizarea costă timp și resurse (deși este foarte, foarte puțin), dar petrecerea unei milisecunde în plus pe ceva poate salva site-ul tău de la a fi hack-uit și distrus.
IMHO, ar trebui să analizezi alte metode pentru a accelera o interogare și să nu compromiți utilizabilitatea și întreținerea. Opțiunea 2 este cu siguranță ceva pe care ar trebui să-l faci pentru temele comerciale.
IDEE (Poate un pic exagerată ;-))
Poți folosi și pre_get_posts
pentru a filtra interogarea ta personalizată și a o face filtrabilă. Este la fel de simplu ca setarea propriului parametru personalizat în interogarea ta și apoi folosirea acelui parametru pentru a ținti interogarea.
În exemplul următor, vom folosi un parametru personalizat query_no
căruia îi vom da valori numerice.
Interogările
$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 );
// Adaugă orice alte argumente suplimentare de setat
}
if ( $q->get( 'query_no' ) == 2 ) {
$q->set( 'post_type', ['post', 'page'] );
// Adaugă orice alte argumente suplimentare de setat
}
if ( $q->get( 'query_no' ) == 3 ) {
$q->set( 'post_status', 'trash' );
// Adaugă orice alte argumente suplimentare de setat
}
} );
Utilizatorul poate acum adăuga argumente suplimentare sau poate schimba cele transmise.
add_action( 'pre_get_posts', function( $q )
{
if ( $q->get( 'query_no' ) == 2 ) {
// Să adăugăm un alt tip de postare
$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 );
// Adaugă orice alte argumente suplimentare de setat
}
},
11 // Asigură-te că aceasta rulează după acțiunea implicită
);

Ce părere ai despre utilizarea transientelor atunci când rezultatele interogărilor sunt aceleași? Exemplu simplu, dar relevant: interogarea este făcută prin ajax ->
setare transient ->
iar când utilizatorul apasă repetat butonul fără a schimba câmpurile de intrare (am setat protecție împotriva spamului pentru butoanele ajax, dar totuși...) ->
obține rezultatele din transiente? Întreb asta pentru că interogarea mea complexă este legată de o hartă, iar acțiunile de panoramare/zoom apelează o interogare exact aceeași deoarece afișarea a ex. 100 000 de markere distruge orice browser.

Aruncă o privire la postările legate sub usort()
. Eu creez nume unice pentru transiente luând argumentele, apoi folosesc md5()
pentru a crea o cheie unică de adăugat la numele transientului. Astfel, dacă argumentele interogării se schimbă, se creează un transient unic. Orice alt apel ulterior cu aceleași argumente va încărca pur și simplu rezultatele din transient.

Scuze, probabil am fost orb pentru că nu am văzut asta înainte... Mulțumesc pentru răspunsul foarte detaliat.
