WP_Query - filtrare sau direct?

2 ian. 2016, 05:01:18
Vizualizări: 13.5K
Voturi: 5

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 și CSS 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ă.

  1. 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
  2. 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:

  1. Mod obișnuit:

    $args = array(
    
            'post_type'         => 'my-post',
            'posts_per_page'    => 8,
            'orderby'           => 'rand', 
        );
    
    }
    
    $results = new WP_Query( $args );
    
  2. 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 );
    
0
Toate răspunsurile la întrebare 1
4

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. Prefer usort() 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ște usort() 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 la WP_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ă
); 
2 ian. 2016 09:02:11
Comentarii

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.

N00b N00b
2 ian. 2016 12:56:22

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.

Pieter Goosen Pieter Goosen
2 ian. 2016 13:46:27

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

N00b N00b
2 ian. 2016 13:49:47

Nici o problemă, încă simțim toți efectele de după revelion, hahahaha. Distrează-te ;-)

Pieter Goosen Pieter Goosen
2 ian. 2016 13:50:47