Dovrei usare Pre Get Posts o WP_Query


29

Ho la seguente query che chiamo nel mio modello taxonomy.php tramite query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Questa funzione funziona perfettamente. Tuttavia, dopo aver letto il codice per i post delle query, ha menzionato pre_get_posts come metodo preferito per modificare la query predefinita. Pre_get_posts sarebbe più efficiente della mia funzione wp_query di seguito?

In tal caso, come dovrei costruire pre_get_posts e passare la mia variabile e la query di seguito?

function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
   global $wp_query; 
   $wp_query = new WP_Query();
   $args = array( 
      'post_type' => $posttype, 
      'post_status' => array($poststatus), 
      'orderby' => 'rand', 
      'posts_per_page' => 30, 
      'meta_query' => array( 
         array( 
            'key' => 'wpcf-paid', 
            'value' => array($paidvalue), 
            'compare' => 'IN', 
            ) 
      ), 
      'tax_query' => array( 
         'relation' => 'AND', 
         array( 
            'taxonomy' => $taxtype, 
            'field' => 'slug', 
            'terms' => $geo 
         ), 
         array( 
            'taxonomy' => 'brands', 
            'field' => 'slug', 
            'terms' => $brands 
         ) 
      ) 
   ); 

   return $wp_query->query($args); 
} 

Risposte:


14

pre_get_postseseguirà la stessa query, quindi entrambi impiegheranno lo stesso tempo. Tuttavia, se si utilizza l' pre_get_postsazione, si salveranno una o più query SQL. In questo momento, WordPress sta eseguendo la query predefinita e quindi esegui la query con questa funzione che sostituisce i risultati della query predefinita (risultante, la query predefinita non è di alcuna utilità). Qui di seguito è come è possibile spostare il $argsa

function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {

    // filter your request here.
    if($query->is_category) {

        $args = array(
            'post_type' => $posttype,
            'post_status' => array($poststatus),
            'orderby' => 'rand',
            'posts_per_page' => 30,
            'meta_query' => array(
                array(
                    'key' => 'wpcf-paid',
                    'value' => array($paidvalue),
                    'compare' => 'IN',
                )
            ),
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => $taxtype,
                    'field' => 'slug',
                    'terms' => $geo
                ),
                array(
                    'taxonomy' => 'brands',
                    'field' => 'slug',
                    'terms' => $brands
                )
            )
        );
        $query->query_vars = $args;
    }
}
add_action('pre_get_posts', 'custom_pre_get_posts');

Grazie mille per la risposta È molto utile. Una domanda veloce. Ho inserito la funzione nel mio file function.php del tema. Eseguo questa funzione custom_pre_get_posts ($ query) dal mio taxonomy.php. Nel taxonomy.php ho impostato le variabili, $ posttype, $ post_status, $ geo, $ brands, $ taxtype ed eseguo due loop cambiando queste variabili. C'è un modo per passare la variabile nella funzione sopra da taxonomy.php? Quando provo custom_pre_get_posts ($ query, 'dealer', 'publishing', '1', $ taxtype, $ geo, $ brands); Ottengo argomento mancante da 2 a 7 per custom_pre_get_posts (). Presumo a causa di add_action ???
user1609391

1
Suppongo che tu abbia modificato custom_pre_get_posts per accettare gli argomenti rimanenti. Sì, stai ricevendo un errore a causa di add_action. add_action chiama questa funzione con argomento singolo (ad esempio $ query), è necessario fornire valori predefiniti ad altri argomenti per evitare errori di argomento mancanti. come ($ posttype = null, $ poststatus = null ...) in modo che possa essere correttamente chiamato da add_action.
MR

MR Grazie per la risposta. Ho letto su Aggiungi azione e vedo che dovrei assegnare una priorità e un numero di argomenti. Quindi ho modificato la mia azione di aggiunta in <code> add_action ('pre_get_posts', 'custom_pre_get_posts', 10,7); </code> Quindi nella mia pagina taxonomy.php ho <code> do_action ('pre_get_post', $ query, ' rivenditori "," pubblicare "," 1 ", $ taxtype, $ geo, $ brands); </code>. Ma sto ancora ricevendo lo stesso errore. Non ero sicuro di dove mettere i valori predefiniti. Ho provato Google ma non sono riuscito a trovare un riferimento. Potete darmi qualche informazione in più su dove gestirlo?
user1609391

Grazie per la risposta e l'esempio. Ma penso che potrei provare a usare pre_get_posts quando dovrei semplicemente fare una nuova query wordpress. Stavo cercando di salvare una query, ma nel mio caso potrebbe non essere possibile. Il motivo è che tutti gli argomenti che hai impostato nel parametro, volevo passare alla funzione dal mio file taxonomy.php. Quindi $ paidvalue = "1" potrebbe essere 1 o 0 a seconda della condizione che sto eseguendo in taxonomy.php. Sembra che pre_get_posts sopra si attivi proprio quando la pagina si carica anche se non chiamo la funzione nel mio file taxonomy.php. Sto vedendo questo corretto?
user1609391

3
Questa risposta non ha senso poiché è attualmente scritta. Sovrascriverete efficacemente qualsiasi valore all'interno $wp_querydell'oggetto e le cose falliranno completamente. A parte questo, semplicemente non è vero che pre_get_postsverrà eseguita una query aggiuntiva ...
Kaiser

10

La risposta tardiva in quanto la risposta più votata interromperà la tua domanda e semplicemente non è vera in alcuni punti importanti.

Il principale WP_Query e i suoi filtri

Innanzitutto, WordPress utilizza internamente query_posts()(un involucro sottile WP_Queryche non dovrebbe essere usato in temi o plugin) per fare un WP_Query. Questo WP_Queryagisce come loop / query principale. Questa query verrà eseguita attraverso molti filtri e azioni finché non viene creata la stringa di query SQL effettiva. Uno di questi è pre_get_posts. Altri sono posts_clauses, posts_whereecc. Che consentono anche di intercettare il processo di creazione della stringa di query.

Uno sguardo approfondito a ciò che accade all'interno del nucleo

WordPress esegue la wp()funzione (in wp-includes/functions.php), che chiama $wp->main()( $wpè un oggetto della classe WP, che è definito in wp-includes/class-wp.php). Questo dice a WordPress di:

  1. Analizza l'URL in una specifica di query usando WP->parse_request()- più su quello sotto.
  2. Impostare tutte le variabili is_ utilizzate dai tag condizionali utilizzando $wp_query->parse_query()( $wp_queryè un oggetto di class WP_Query, che è definito in wp-includes/query.php). Si noti che nonostante il nome di questa funzione, in questo caso in WP_Query->parse_queryrealtà non esegue alcuna analisi per noi, dal momento che viene eseguito in anticipo WP->parse_request().
  3. Converti la specifica della query in una query del database MySQL ed esegui la query del database per ottenere l'elenco dei post, nella funzione WP_Query-> get_posts (). Salvare i post nell'oggetto $ wp_query da utilizzare nel ciclo di WordPress.

Codice sorgente

Conclusione

Se desideri davvero modificare la query principale, puoi utilizzare un'ampia varietà di filtri. Basta usare $query->set( 'some_key', 'some_value' );per modificare i dati lì o usare $query->get( 'some_key' );per recuperare i dati per fare controlli condizionali. Questo ti salverà dal fare una seconda query, poiché stai modificando solo la query SQL.

Se devi fare una query aggiuntiva , vai con un WP_Queryoggetto. Ciò aggiungerà un'altra query al DB.

Esempio

Dato che le risposte funzionano sempre meglio con un esempio, qui ne hai uno davvero bello (oggetti di scena di Brad Touesnard), che estende semplicemente l'oggetto principale e quindi è abbastanza riutilizzabile (crea un plugin):

class My_Book_Query extends WP_Query
{
    function __construct( $args = array() )
    {
        // Forced/default args
        $args = array_merge( $args, array(
            'posts_per_page' => -1
        ) );

        add_filter( 'posts_fields', array( $this, 'posts_fields' ) );

        parent::__construct( $args );
    }

    public function posts_fields( $sql )
    {
        return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
    }
}

È quindi possibile eseguire la seconda / query aggiuntiva come si può vedere nell'esempio seguente. Non dimenticare di reimpostare la query in seguito.

$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
    while ( $book_query->have_posts() )
    {
        $book_query->the_post();
        # ...do stuff...
    } // endwhile;
    wp_reset_postdata();
} // endif;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.