Tôi có thể buộc WP_Query không trả lại kết quả không?


23

Tôi đang làm việc trên một trang web với tính năng tìm kiếm cho phép người dùng tìm kiếm thông qua rất nhiều meta bài đăng. Có một mẫu tìm kiếm cụ thể mà tôi muốn buộc không trả lại kết quả nào. Về mặt kỹ thuật, WP_Query sẽ tìm thấy kết quả trong cơ sở dữ liệu, nhưng tôi muốn ghi đè lên bằng cách nào đó để buộc nó không trả về kết quả nào để kích hoạt if( $example->have_posts() )lỗi.

Có một số loại tham số tôi có thể truyền cho WP_Query như thế 'force_no_results' => truesẽ buộc nó không trả về kết quả?


1
CNTT có vẻ như bạn đang yêu cầu triển khai đã được xác định, thay vì hỏi cách giải quyết vấn đề gốc. Đọc giữa các dòng, tôi nghĩ điều bạn thực sự nên hỏi là: làm thế nào để tôi tạo một mẫu tìm kiếm cụ thể không cần thiết? . Nguyên nhân WP_Query()trả về không có kết quả có thể hoặc không phải là cách tốt nhất để trả lời câu hỏi đó. Nó cũng có thể hữu ích nếu bạn mô tả mẫu tìm kiếm mà bạn muốn không cần thiết. Biết mô hình tìm kiếm có thể giúp tìm ra giải pháp.
Chip Bennett

Câu trả lời:


28

Thử

'post__in' => array(0)

Ngắn gọn và đúng trọng tâm.


Suy nghĩ đầu tiên của tôi là - điều này phải đi sai ở đâu đó, nhưng từ việc lướt qua mã liên quan, điều này thực sự sẽ hoạt động khá độc đáo. :)
Rarst

5
số 0 rất quan trọng vì chỉ một mảng trống sẽ trả về các bài đăng gần đây.
Đánh dấu Kaplun

Cảm ơn! Điều này đã giải quyết một lỗi cho tôi khi post__intrả về các bài đăng khi vượt qua một mảng trống ... array(0)hoạt động rất tốt! Điều này thật kỳ lạ nhưng nó thực sự có thể được theo dõi bởi một vấn đề xuất hiện trong lõi WP là một lỗi nhưng sau đó vẫn bị bỏ qua vì quá nhiều nhà phát triển chủ đề / plugin đã xây dựng chức năng xung quanh nó -_- core.trac.wordpress.org/ vé / 28099
EranSch

3

Thật kỳ lạ là không có cách rõ ràng / rõ ràng để ngắn mạch WP_Query.

Nếu đó là truy vấn chính, bạn có thể tìm ra thứ gì đó xung quanh WP->parse_request(), dường như có do_parse_requestbộ lọc tương đối gần đây (3.5) .

Nhưng đối với WP_Querybản thân các bản hack bẩn thường theo thứ tự, chẳng hạn như truy vấn SQL ngắn mạch bằng cách thêm AND 1=0qua posts_wherebộ lọc, v.v.


2
Cảm ơn bạn về thông tin. Đó là một vòng lặp thứ cấp btw. Và tôi cuối cùng đã thực hiện một hack bẩn như "post_type" => "break_loop"loại bài đăng không tồn tại.
Brian

2

Các vấn đề về đặt tham số truy vấn thành giá trị không tồn tại là 2:

  • Truy vấn sẽ chạy, vì vậy ngay cả khi bạn đã biết sẽ không có kết quả, vẫn có một giá thực hiện nhỏ phải trả
  • Các truy vấn WordPress có 19 'posts_*'móc lọc khác nhau ( 'posts_where',, 'post_join'v.v.) hoạt động theo truy vấn, do đó bạn không bao giờ có thể chắc chắn rằng ngay cả việc đặt tham số không tồn tại, truy vấn không trả về kết quả, một ORmệnh đề đơn giản được bộ lọc trả về sẽ trả về một cái gì đó.

Bạn cần một chút Hardcore thường xuyên để được chắc chắn một truy vấn trở lại không có kết quả và không có (hoặc rất minimun) vấn đề hiệu suất.

Để kích hoạt thói quen đó, bạn có thể sử dụng mọi phương thức, về mặt kỹ thuật bạn có thể chuyển bất kỳ đối số nào cho các đối số WP_Querysự kiện không tồn tại.

Vì vậy, nếu bạn thích một cái gì đó như 'force_no_results' => true, bạn có thể sử dụng nó như vậy:

$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );

và thêm một cuộc gọi lại chạy trên 'pre_get_posts'đó làm công việc khó khăn:

add_action( 'pre_get_posts', function( $q ) {
  if (array_key_exists('force_no_results', $q->query) && $q->query['force_no_results']) {
    $q->query = $q->query_vars = array();
    $added = array();
    $filters = array(
      'where', 'where_paged', 'join', 'join_paged', 'groupby', 'orderby', 'distinct',
      'limits', 'fields', 'request', 'clauses', 'where_request', 'groupby_request',
      'join_request', 'orderby_request', 'distinct_request','fields_request',
      'limits_request', 'clauses_request'
    );
    // remove all possible interfering filter and save for later restore
    foreach ( $filters as $f ) {
      if ( isset($GLOBALS['wp_filter']["posts_{$f}"]) ) {
        $added["posts_{$f}"] = $GLOBALS['wp_filter']["posts_{$f}"];
        unset($GLOBALS['wp_filter']["posts_{$f}"]);
      }
    }
    // be sure filters are not suppressed
    $q->set( 'suppress_filters', FALSE );
    $done = 0;
    // use a filter to return a non-sense request
    add_filter('posts_request', function( $r ) use( &$done ) {
      if ( $done === 0 ) { $done = 1;
        $r = "SELECT ID FROM {$GLOBALS['wpdb']->posts} WHERE 0 = 1";
      }
      return $r;
    });
    // restore any filter that was added and we removed
    add_filter('posts_results', function( $posts ) use( &$done, $added ) {
      if ( $done === 1 ) { $done = 2;
        foreach ( $added as $hook => $filters ) {
          $GLOBALS['wp_filter'][$hook] = $filters;
        }
      }
      return $posts;
    });
  }
}, PHP_INT_MAX );

Những gì mã này làm là chạy 'pre_get_posts'càng muộn càng tốt. Nếu đối số 'force_no_results' xuất hiện trong truy vấn, thì:

  1. trước tiên hãy xóa tất cả các bộ lọc có thể có thể can thiệp vào truy vấn và lưu trữ chúng bên trong một mảng trợ giúp
  2. sau khi chắc chắn bộ lọc được kích hoạt, bộ lọc adda trả về loại yêu cầu này: SELECT ID FROM wp_posts WHERE 0 = 1một khi tất cả các bộ lọc bị xóa, không có khả năng truy vấn này bị thay đổi và nó rất nhanh và không có kết quả chắc chắn
  3. ngay sau khi truy vấn này được chạy, tất cả các bộ lọc ban đầu (nếu có) được khôi phục và tất cả các truy vấn tiếp theo sẽ hoạt động như mong đợi.
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.