Czy powinienem użyć Pre Get Posts lub WP_Query

29

Mam następujące zapytanie, które wywołuję w moim szablonie taxonomy.php za pośrednictwem query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Ta funkcja działa idealnie. Jednak po przeczytaniu kodeksu dla postów zapytania wspomniał o pre_get_posts jako preferowanym sposobie zmiany domyślnego zapytania. Czy pre_get_posts byłyby bardziej wydajne niż moja funkcja wp_query poniżej?

Jeśli tak, to jak mam zbudować pre_get_posts i przekazać moją zmienną i zapytanie poniżej?

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); 
} 
użytkownik1609391
źródło

Odpowiedzi:

14

pre_get_postsuruchomi to samo zapytanie, więc oba zajmą ten sam czas. Ale jeśli użyjesz pre_get_postsakcji, zapiszesz jedno lub więcej zapytań SQL. W tej chwili WordPress uruchamia domyślne zapytanie, a następnie uruchamiasz zapytanie za pomocą tej funkcji, która zastępuje wyniki domyślnego zapytania (wynikowe, domyślne zapytanie nie ma zastosowania). Poniżej jest to, jak można przenieść $argsTO

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');
PAN
źródło
Dziękuję Ci bardzo za odpowiedź. To bardzo pomocne. Jedno szybkie pytanie. Umieściłem funkcję w moim pliku theme.php kompozycji. Korzystam z tej funkcji custom_pre_get_posts ($ query) z mojego taxonomy.php. W taxonomy.php ustawiam zmienne, $ posttype, $ post_status, $ geo, $ brand, $ taxtype i uruchamiam dwie pętle zmieniając te zmienne. Czy istnieje sposób na przekazanie zmiennej do powyższej funkcji z pliku taksonomy.php? Kiedy próbuję custom_pre_get_posts ($ query, „dealers”, „publish”, „1”, $ taxtype, $ geo, $ brand); Dostaję brakujący argument od 2 do 7 dla custom_pre_get_posts (). Zakładam, że z powodu dodatkowej aktywności ???
user1609391,
1
Zakładam, że zmieniłeś custom_pre_get_posts, aby zaakceptować pozostałe argumenty. Tak, pojawia się błąd z powodu dodatkowej aktywności. add działań wywołuje tę funkcję z pojedynczym argumentem (np. $ query), powinieneś nadać wartości domyślne innym argumentom, aby uniknąć błędów braku argumentów. jak ($ ​​posttype = null, $ poststatus = null ...), aby można go było poprawnie wywołać przez dodanie działań.
MR
MR Dziękuję za odpowiedź. Czytam po dodaniu akcji i widzę, że powinienem przypisać priorytet i liczbę argumentów. Zmieniłem więc akcję dodawania na <code> add działań („pre_get_posts”, „custom_pre_get_posts”, 10,7); </code> Następnie na mojej stronie taksonomy.php <code> do współdziałania („pre_get_post”, $ zapytanie, ” dealerzy ”,„ publikuj ”,„ 1 ”, $ typ podatku, $ geo, $ marki); </code>. Ale wciąż pojawia się ten sam błąd. Nie byłem pewien, gdzie umieścić wartości domyślne. Próbowałem google, ale nie mogłem znaleźć referencji. Czy możesz podać mi trochę więcej informacji na temat tego, jak sobie z tym poradzić?
user1609391,
Dziękuję za odpowiedź i przykład. Ale myślę, że mogę próbować używać pre_get_posts, kiedy powinienem po prostu tworzyć nowe zapytanie Wordpress. Próbowałem zapisać zapytanie, ale w moim przypadku może nie być to możliwe. Powodem są wszystkie argumenty ustawione w parametrze, które chciałem przekazać do funkcji z mojego pliku taxonomy.php. Więc $ paidvalue = ”1” może wynosić 1 lub 0 w zależności od tego, który warunek wykonuję w taxonomy.php. Wygląda na to, że pre_get_posts powyżej odpala zaraz po załadowaniu strony, nawet jeśli nie wywołam funkcji w moim pliku taxonomy.php. Czy widzę to poprawnie?
user1609391,
3
Ta odpowiedź nie ma sensu, ponieważ jest obecnie napisana. Skutecznie zastąpisz każdą wartość wewnątrz $wp_queryobiektu, a wszystko całkowicie zawiedzie. Poza tym po prostu nie jest prawdą, że pre_get_postsuruchomi dodatkowe zapytanie ...
Kaiser
10

Późna odpowiedź, ponieważ najbardziej uprzywilejowana odpowiedź złamie twoje zapytanie i po prostu nie jest prawdziwa w niektórych głównych punktach.

Główny WP_Query i to filtry

Po pierwsze, WordPress używa wewnętrznie query_posts()(cienkie opakowanie, WP_Queryktóre nie powinno być używane w kompozycjach lub wtyczkach) do zrobienia WP_Query. Działa WP_Queryto jako główna pętla / zapytanie. To zapytanie będzie działać przez wiele filtrów i działań, dopóki nie zostanie utworzony rzeczywisty ciąg zapytania SQL. Jednym z nich jest pre_get_posts. Inne są posts_clauses, posts_whereitd, które również pozwalają na przechwycenie procesu budowania ciąg kwerendy.

Dogłębne spojrzenie na to, co dzieje się w rdzeniu

WordPress uruchamia wp()funkcję (in wp-includes/functions.php), która wywołuje $wp->main()( $wpjest to obiekt klasy WP, który jest zdefiniowany w wp-includes/class-wp.php). Mówi to WordPressowi:

  1. Parsuj adres URL do specyfikacji zapytania za pomocą WP->parse_request()- więcej na ten temat poniżej.
  2. Ustaw wszystkie zmienne is_, które są używane przez tagi warunkowe, używając $wp_query->parse_query()( $wp_queryjest to obiekt class WP_Queryzdefiniowany w wp-includes/query.php). Zauważ, że pomimo nazwy tej funkcji, w tym przypadku WP_Query->parse_querytak naprawdę nie wykonuje dla nas żadnej analizy, ponieważ odbywa się to wcześniej WP->parse_request().
  3. Konwertuj specyfikację zapytania na zapytanie do bazy danych MySQL i uruchom zapytanie do bazy danych, aby uzyskać listę postów, w funkcji WP_Query-> get_posts (). Zapisz posty w obiekcie $ wp_query do użycia w pętli WordPress.

Kod źródłowy

Wniosek

Jeśli naprawdę chcesz zmodyfikować główne zapytanie, możesz użyć szerokiej gamy filtrów. Po prostu użyj, $query->set( 'some_key', 'some_value' );aby zmienić tam dane lub użyj, $query->get( 'some_key' );aby pobrać dane w celu sprawdzenia warunkowego. Pozwoli to zaoszczędzić od robienia drugie zapytanie, jak jesteś zmieniając tylko zapytania SQL.

Jeśli musisz wykonać dodatkowe zapytanie, przejdź do WP_Queryobiektu. Spowoduje to dodanie kolejnego zapytania do bazy danych.

Przykład

Ponieważ odpowiedzi zawsze działają lepiej na przykładzie, masz tutaj naprawdę fajny (rekwizyty dla Brada Touesnarda), który po prostu rozszerza główny obiekt i dlatego jest dość wielokrotnego użytku (stwórz z niego wtyczkę):

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'";
    }
}

Następnie możesz uruchomić drugie / dodatkowe zapytanie, jak pokazano w poniższym przykładzie. Nie zapomnij później zresetować zapytania.

$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;
kajzer
źródło