Xóa truy vấn trang chủ


8

Tôi có một trang chủ hiển thị home.phpmẫu, chứa 2 thanh bên với các widget trong đó.

Truy vấn chính vẫn có trong 10 bài đăng tiêu chuẩn, nhưng vì tôi không hiển thị những bài này, nên tôi muốn loại bỏ hoàn toàn truy vấn được thực hiện cho cơ sở dữ liệu. Nếu cần, một vòng lặp bài trống sẽ làm như tôi không sử dụng vòng lặp chính trong home.phpmẫu của mình .

Làm thế nào tôi sẽ làm điều này? Tôi có thể sử dụng pre_get_postsđể giảm thiểu và giảm truy vấn, nhưng điều đó vẫn để lại cho tôi một truy vấn rất nhanh, làm cách nào để loại bỏ nó hoàn toàn?


1
Câu hỏi này có vẻ đáng đọc. Nhưng nếu bạn hỏi tôi, tôi sẽ sử dụng mẫu của riêng mình và đặt nó làm trang chủ tĩnh từ cài đặt, bởi vì trong khi có thể, điều đó không đáng. Đọc thú vị hơn ở đây . Hoặc là tất cả hoặc tôi hoàn toàn bỏ lỡ điểm câu hỏi của bạn.
N00b

Câu trả lời:


7

Bộ posts_requestlọc

Lướt qua WP_Querychúng tôi thấy phần quan tâm này:

if ( !$q['suppress_filters'] ) {
    /**
     * Filter the completed SQL query before sending.
     *
     * @since 2.0.0
     *
     * @param array    $request The complete SQL query.
     * @param WP_Query &$this   The WP_Query instance (passed by reference).
     */
      $this->request = apply_filters_ref_array( 'posts_request', 
          array( $this->request, &$this ) );
   }

   if ( 'ids' == $q['fields'] ) {
       $this->posts = $wpdb->get_col( $this->request );
       $this->posts = array_map( 'intval', $this->posts );
       $this->post_count = count( $this->posts );
       $this->set_found_posts( $q, $limits );
       return $this->posts;
   }

Chúng tôi có thể cố gắng loại bỏ yêu cầu nhà chính thông qua posts_requestbộ lọc. Đây là một ví dụ:

add_filter( 'posts_request', function( $request, \WP_Query $q )
{
    // Target main home query
    if ( $q->is_home() && $q->is_main_query() )
    {
        // Our early exit
        $q->set( 'fields', 'ids' );

        // No request
        $request = '';
    }

    return $request;    

}, PHP_INT_MAX, 2 );

nơi chúng tôi buộc phải 'fields' => 'ids'thoát ra sớm.

Bộ posts_pre_querylọc (WP 4.6+)

Chúng tôi cũng có thể sử dụng bộ lọc posts_pre_querysrc mới có sẵn trong WordPress 4.6+

add_filter( 'posts_pre_query', function( $posts, \WP_Query $q )
{
    if( $q->is_home() && $q->is_main_query() )
    {
        $posts = [];
        $q->found_posts = 0;
    }
    return $posts;
}, 10, 2 );

Bộ lọc này làm cho nó có thể bỏ qua các truy vấn cơ sở dữ liệu thông thường để thực hiện tiêm bài tùy chỉnh thay thế.

Tôi chỉ thử nghiệm điều này và nhận thấy rằng điều này sẽ không ngăn chặn các bài viết dính, ngược lại với posts_requestcách tiếp cận.

Kiểm tra vé # 36687 để biết thêm thông tin và ví dụ ở đó bởi @boonebgorges.


Rất giống với những gì tôi vừa viết, nhưng tôi đã không phát hiện ra phần id của các trường, điều đó đã loại bỏ 2 truy vấn khác, cảm ơn!
Tom J Nowell

1
Tuyệt vời, đôi khi tôi nghĩ rằng sẽ tốt như thế nào khi có một cách dễ dàng để thoát WP_Querysớm, ví dụ như thông qua một đối số như 'skip_query' => truehoặc thậm chí qua một bộ lọc, nhưng sau đó tôi nhận ra rằng có thể dễ dàng gây rối các trang web trên internet như thế nào nhiều cách ;-) @TomJNowell
birgire

Có một bộ lọc split_the_queryngay bên dưới các dòng, làm chính xác như vậy nhưng tôi tự hỏi nó không làm giảm số lượng truy vấn!
Sumit

Giải pháp tuyệt vời, thậm chí tôi đã bỏ lỡ 'fields' => 'ids', và tôi sử dụng nó rất nhiều ;-)
Pieter Goosen

2

Đây là một mẹo gọn gàng mà tôi học được từ @birgire, chúng ta có thể tạm dừng truy vấn chính bằng cách thêm AND where 0=1vào WHEREmệnh đề của truy vấn SQL. Điều này vẫn có thể dẫn đến một truy vấn db, nhưng chắc chắn nó sẽ ngăn truy vấn chính truy vấn các bài đăng

add_filter( 'posts_where', function ( $where, \WP_Query $q )
{
    if (    $q->is_home()
         && $q->is_main_query()
    ) {
        $where .= ' AND where 0 = 1';
    }

    return $where;
}, 10, 2 ); 

Bạn cũng có thể chỉ cần cố gắng thay thế WHEREmệnh đề bằngwhere 0 = 1

$where = ' where 0 = 1';

thay vì

$where .= ' AND where 0 = 1';

Thật không may, tôi không có thời gian để kiểm tra bất cứ điều gì, nhưng đây sẽ là một điểm khởi đầu tốt đẹp


Điều này nghe có vẻ như là gần nhất tôi có thể nhận được những gì tôi yêu cầu, hoặc ít nhất, truy vấn được tối ưu hóa mạnh mẽ nhất, tôi sẽ xem xét điều này trong khi điều tra xem liệu truy vấn đó có thể bị xóa hay không
Tom J Nowell

+1 để chia sẻ ý tưởng này. Nhưng tôi đã thử nó và nó giảm thời gian 2 ms :)
Sumit

Tôi ước tôi có thể nhớ tôi đã học nó từ đâu, nhưng điều này cũng được sử dụng bởi cốt lõi ;-) Tôi nghĩ rằng sẽ rất tốt nếu bỏ qua các que $q->set( 'ignore_sticky_posts', true );chỉ trong trường hợp.
bạch dương

@birgire Điểm tuyệt vời. Ngay cả với giải pháp của tôi, bạn vẫn nhận được gậy từ truy vấn chính ;-)
Pieter Goosen

2

Để tham khảo, trước: 45q, sau: 42q

Mã này rất giống với mã được sử dụng bởi @birgire

function _tomjn_home_cancel_query( $query, \WP_Query $q ) {
    if ( !$q->is_admin() && !$q->is_feed() && $q->is_home() && $q->is_main_query() ) {
        $query = false;
        $q->set( 'fields', 'ids' );
    }
    return $query;
}
add_filter( 'posts_request', '_tomjn_home_cancel_query', 100, 2 );
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.