Чи слід використовувати дописи на попереднє отримання або WP_Query


29

У мене є наступний запит, який я викликаю у своєму шаблоні taxonomy.php через query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Ця функція працює чудово. Однак після прочитання кодексу для публікацій запиту він згадував pre_get_posts як кращий спосіб зміни запиту за замовчуванням. Чи буде pre_get_posts більш ефективним, ніж моя функція wp_query нижче?

Якщо так, то як я буду сконструювати pre_get_posts і передавати свою змінну та запит нижче?

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); 
} 

Відповіді:


14

pre_get_postsзапустить один і той же запит, тому обидва займуть однаковий час. Але, якщо ви будете використовувати pre_get_postsдію, ви збережете один або кілька запитів SQL. Зараз WordPress виконує запит за замовчуванням, а потім ви запускаєте свій запит за допомогою цієї функції, яка замінює результати запиту за замовчуванням (в результаті запит за замовчуванням не приносить користі). Нижче , як ви можете перемістити $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');

Дуже дякую за відповідь. Це дуже корисно. Одне швидке запитання. Я розмістив цю функцію у своєму тематичному файлі function.php. Я запускаю цю функцію custom_pre_get_posts ($ query) з моєї таксономії.php. У taxonomy.php я встановив змінні, $ posttype, $ post_status, $ geo, $ марки, $ taxtype і запускаю дві петлі, змінюючи цю змінну. Чи є спосіб передати змінну у вищевказану функцію з таксономії.php? Коли я пробую custom_pre_get_posts ($ query, 'дилери', 'публікувати', '1', $ taxtype, $ geo, $ марки); Я отримую відсутній аргумент 2 через 7 для custom_pre_get_posts (). Я припускаю, що завдяки додаванню ???
user1609391

1
Я припускаю, що ви змінили custom_pre_get_posts, щоб прийняти решту аргументів. Так, ви отримуєте помилку через додавання. добавлення викликає цю функцію за допомогою одного аргументу (тобто $ query), ви повинні надати значення за замовчуванням для інших аргументів, щоб уникнути пропущених помилок аргументу. як ($ posttype = null, $ poststatus = null ...), тому його можна правильно викликати додаванням.
MR

MR Дякую за відповідь. Я читаю про додавання дії і бачу, що мені слід призначити пріоритет та номер аргументів. Тож я змінив свою дію на додавання на <код> додавання ('pre_get_posts', 'custom_pre_get_posts', 10,7); </code> Потім на своїй сторінці таксономії.php я <code> dogery ('pre_get_post', $ query, ' дилерів ',' опублікувати ',' 1 ', $ taxtype, $ geo, $ брендів); </code>. Але я все одно отримую ту саму помилку. Я не був впевнений, куди поставити значення за замовчуванням. Я спробував google, але не зміг знайти посилання. Чи можете ви дати мені трохи більше інформації про те, де з цим впоратися?
user1609391

Дякую за відповідь та приклад. Але я думаю, що я, можливо, намагаюся використовувати pre_get_posts, коли мені просто слід робити новий запит на wordpress. Я намагався зберегти запит, але в моєму випадку це може бути неможливо. Причиною є всі аргументи, які ви задаєте в параметрі, я хотів перейти до функції з мого файлу taxonomy.php. Отже, $ paidvalue = "1" може бути 1 або 0 залежно від того, яку умову я виконую в таксономії.php. Здається, що pre_get_posts вище запускає право, коли сторінка завантажується, навіть якщо я не викликаю функцію в моєму файлі taxonomy.php. Я бачу це правильно?
user1609391

3
Ця відповідь не має сенсу, як це написано в даний час. Ви будете ефективно перезаписувати будь-яке значення всередині $wp_queryоб'єкта, і все повністю вийде з ладу. Крім цього, це просто неправда, що pre_get_postsбуде запущений додатковий запит ...
kaiser

10

Пізня відповідь, як найбільш актуальна відповідь, порушить ваш запит і просто не відповідає дійсності деяких основних пунктів.

Основний WP_Query і це фільтри

По-перше, WordPress використовує внутрішньо query_posts()(тонку обгортку, WP_Queryяку не слід використовувати в темах чи плагінах), щоб зробити це WP_Query. Це WP_Queryвиступає в якості основного циклу / запиту. Цей запит виконуватиметься безліч фільтрів та дій, поки не буде створена фактична рядок запиту SQL. Одне з таких є pre_get_posts. Інші - це posts_clausesі posts_whereт. Д., Які також дозволяють перехопити процес побудови рядка запиту.

Поглиблено подивіться, що відбувається всередині ядра

WordPress запускає wp()функцію (in wp-includes/functions.php), яка викликає $wp->main()( $wpє об'єктом класу WP, який визначено в wp-includes/class-wp.php). Це повідомляє WordPress:

  1. Розбирайте URL-адресу в специфікації запиту, використовуючи WP->parse_request()- докладніше про це нижче.
  2. Встановіть усі змінні is_, які використовуються умовними тегами за допомогою $wp_query->parse_query()( $wp_queryє об'єктом class WP_Query, який визначено в wp-includes/query.php). Зауважте, що, незважаючи на ім’я цієї функції, у цьому випадку WP_Query->parse_queryнасправді не робиться для нас жодного аналізу, оскільки це робиться попередньо WP->parse_request().
  3. Перетворіть специфікацію запиту в запит бази даних MySQL та запустіть запит бази даних, щоб отримати список публікацій, у функції WP_Query-> get_posts (). Збережіть публікації в об’єкті $ wp_query, який буде використовуватися в циклі WordPress.

Вихідний кодекс

Висновок

Якщо ви дійсно хочете змінити основний запит, тоді ви можете використовувати найрізноманітніші фільтри. Просто використовуйте $query->set( 'some_key', 'some_value' );для зміни там даних або використовуйте $query->get( 'some_key' );для отримання даних для проведення умовних перевірок. Це позбавить вас від виконання другого запиту, так як ви зміни тільки запит SQL.

Якщо вам доведеться зробити додатковий запит, тоді перейдіть з WP_Queryоб’єктом. Це додасть ще один запит до БД.

Приклад

Оскільки відповіді завжди краще спрацьовують із прикладом, ви тут отримали один дуже приємний (реквізит до Бреда Туеснарда), який просто розширює основний об'єкт і тому є досить багаторазовим використання (зробіть із нього плагін):

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

Потім ви можете запустити свій другий / додатковий запит, як ви бачите в наступному прикладі. Не забудьте після цього скинути запит.

$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;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.