Tôi nên sử dụng Pre Get Post hay WP_Query


29

Tôi có truy vấn sau đây mà tôi gọi trong mẫu taxonomy.php của mình thông qua query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Chức năng này hoạt động hoàn hảo. Tuy nhiên, sau khi đọc codex cho các bài đăng truy vấn, nó đã đề cập đến pre_get_posts như một cách ưa thích để thay đổi truy vấn mặc định. Các pre_get_posts sẽ hiệu quả hơn sau đó hàm wp_query của tôi bên dưới?

Nếu vậy, làm thế nào tôi có thể xây dựng pre_get_posts và vượt qua biến và truy vấn của tôi dưới đây?

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

Câu trả lời:


14

pre_get_postssẽ chạy cùng một truy vấn, vì vậy cả hai sẽ mất cùng thời gian. Nhưng, nếu bạn sử dụng pre_get_postshành động, bạn sẽ lưu một hoặc nhiều truy vấn SQL. Ngay bây giờ, WordPress đang chạy truy vấn mặc định và sau đó bạn chạy truy vấn của mình với chức năng này thay thế kết quả của truy vấn mặc định (kết quả là truy vấn mặc định không được sử dụng). Dưới đây là cách bạn có thể di chuyển $argsđến

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

Cảm ơn bạn rất nhiều cho trả lời. Nó rất hữu ích. Một câu hỏi nhanh. Tôi đã đặt chức năng trong tập tin function.php của chủ đề. Tôi chạy hàm này custom_pre_get_posts ($ query) từ taxonomy.php của tôi. Trong taxonomy.php, tôi thiết lập các biến, $ posttype, $ post_status, $ Geo, $ thương hiệu, $ taxtype và chạy hai vòng thay đổi các biến này. Có cách nào để chuyển biến vào hàm trên từ taxonomy.php không? Khi tôi thử custom_pre_get_posts ($ truy vấn, 'đại lý', 'xuất bản', '1', $ taxtype, $ Geo, $ nhãn hiệu); Tôi nhận được đối số Thiếu 2 đến 7 cho custom_pre_get_posts (). Tôi giả sử do add_action ???
user1609391

1
Tôi giả sử bạn đã thay đổi custom_pre_get_posts để chấp nhận các đối số còn lại. Có, bạn đang gặp lỗi vì add_action. add_action gọi hàm này với một đối số (ví dụ $ query), bạn nên cung cấp các giá trị mặc định cho các đối số khác để tránh bỏ sót lỗi đối số. like ($ posttype = null, $ poststatus = null ...) để nó có thể được gọi đúng bởi add_action.
MR

MR Cảm ơn bạn đã trả lời. Tôi đọc lên thêm hành động và tôi thấy tôi nên gán một số ưu tiên và số đối số. Vì vậy, tôi đã thay đổi hành động thêm của mình thành <code> add_action ('pre_get_posts', 'custom_pre_get_posts', 10,7); </ code> Sau đó, trong trang taxonomy.php của tôi, tôi <code> do_action ('pre_get_post', $ query, 'query đại lý ',' xuất bản ',' 1 ', $ taxtype, $ Geo, $ thương hiệu); </ code>. Nhưng tôi vẫn nhận được cùng một lỗi. Tôi không chắc chắn nơi để đặt các giá trị mặc định. Tôi đã thử google nhưng không thể tìm thấy tài liệu tham khảo. Bạn có thể cho tôi thêm một chút thông tin về cách xử lý việc này không?
dùng1609391

Cảm ơn bạn đã trả lời và ví dụ. Nhưng tôi nghĩ rằng tôi có thể đang cố gắng sử dụng pre_get_posts khi tôi nên thực hiện một truy vấn wordpress mới. Tôi đã cố gắng lưu một truy vấn, nhưng trong trường hợp của tôi, nó có thể không thể. Lý do là tất cả các đối số bạn đặt trong tham số, tôi muốn chuyển đến hàm từ tệp taxonomy.php của mình. Vì vậy, $ payvalue = 1, 1 có thể là 1 hoặc 0 tùy thuộc vào điều kiện tôi đang thực hiện trong taxonomy.php. Có vẻ như pre_get_posts ở trên sẽ kích hoạt ngay khi trang tải ngay cả khi tôi không gọi hàm trong tệp taxonomy.php của mình. Tôi có thấy điều này đúng không?
dùng1609391

3
Câu trả lời này là vô nghĩa vì nó hiện đang được viết. Bạn sẽ ghi đè lên bất kỳ giá trị nào bên trong $wp_queryđối tượng và mọi thứ sẽ hoàn toàn thất bại. Bên cạnh đó nó chỉ đơn giản là không đúng sự thậtpre_get_postssẽ chạy một truy vấn thêm ...
kaiser

10

Câu trả lời muộn vì câu trả lời được đánh giá cao nhất sẽ phá vỡ truy vấn của bạn và đơn giản là không đúng ở một số điểm chính.

Các chính WP_Query và bộ lọc của nó

Đầu tiên, WordPress nội bộ sử dụng query_posts()(một wrapper mỏng xung quanh WP_Querykhông nên được sử dụng trong chủ đề hoặc bổ sung) để làm một WP_Query. Đây WP_Querylà hoạt động như vòng lặp / truy vấn chính. Truy vấn này sẽ chạy qua rất nhiều bộ lọc và hành động cho đến khi chuỗi truy vấn SQL thực tế được xây dựng. Một trong số đó là pre_get_posts. Những người khác posts_clauses, posts_wherevv mà còn cho phép bạn ngăn chặn quá trình xây dựng chuỗi truy vấn.

Một cái nhìn sâu sắc về những gì xảy ra bên trong lõi

WordPress chạy wp()hàm (in wp-includes/functions.php), gọi $wp->main()( $wplà một đối tượng của lớp WP, được định nghĩa trong wp-includes/class-wp.php). Điều này nói với WordPress về:

  1. Phân tích URL thành một đặc tả truy vấn bằng cách sử dụng WP->parse_request()- nhiều hơn về điều đó bên dưới.
  2. Đặt tất cả các biến is_ được sử dụng bởi Thẻ có điều kiện bằng cách sử dụng $wp_query->parse_query()( $wp_querylà một đối tượng của class WP_Query, được xác định trong wp-includes/query.php). Lưu ý rằng mặc dù tên của hàm này, trong trường hợp WP_Query->parse_querynày thực tế không thực hiện bất kỳ phân tích cú pháp nào cho chúng tôi, vì điều đó được thực hiện trước đó WP->parse_request().
  3. Chuyển đổi đặc tả truy vấn thành truy vấn cơ sở dữ liệu MySQL và chạy truy vấn cơ sở dữ liệu để lấy danh sách các bài đăng, trong chức năng WP_Query-> get_posts (). Lưu các bài đăng trong đối tượng $ wp_query sẽ được sử dụng trong Vòng lặp WordPress.

Codex nguồn

Phần kết luận

Nếu bạn thực sự muốn sửa đổi truy vấn chính, thì bạn có thể sử dụng nhiều bộ lọc khác nhau. Chỉ cần sử dụng $query->set( 'some_key', 'some_value' );để thay đổi dữ liệu ở đó hoặc sử dụng $query->get( 'some_key' );để truy xuất dữ liệu để thực hiện kiểm tra có điều kiện. Điều này sẽ giúp bạn không phải thực hiện truy vấn thứ hai, vì bạn chỉ thay đổi truy vấn SQL.

Nếu bạn phải thực hiện một truy vấn bổ sung , sau đó đi với một WP_Queryđối tượng. Điều này sẽ thêm một truy vấn khác vào DB.

Thí dụ

Vì các câu trả lời luôn hoạt động tốt hơn với một ví dụ, bạn ở đây có một câu trả lời rất hay (đạo cụ cho Brad Touesnard), chỉ đơn giản là mở rộng đối tượng cốt lõi và do đó khá dễ sử dụng lại (tạo một plugin từ nó):

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

Sau đó, bạn có thể chạy truy vấn thứ hai / bổ sung như bạn có thể thấy trong ví dụ sau. Đừng quên đặt lại truy vấn của bạn sau đó.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.