WP_Query가 결과를 반환하지 않도록 할 수 있습니까?


23

사용자가 많은 게시물 메타를 통해 검색 할 수있는 검색 기능이있는 웹 사이트에서 작업하고 있습니다. 결과를 강제로 반환하지 않는 특정 검색 패턴이 있습니다. WP_Query는 기술적으로 데이터베이스에서 결과를 찾을 수 있지만 if( $example->have_posts() )실패 를 유발하는 결과를 반환하지 않도록 강제로 무시하고 싶습니다 .

WP_Query에 전달할 수있는 일종의 매개 변수가 있습니까? 그렇지 'force_no_results' => true않으면 결과가 반환되지 않습니다.


1
IT는 근본적인 문제를 해결하는 방법을 묻기보다는 이미 결정된 구현을 요구하는 것 같습니다. 줄 사이를 읽으면서 실제로 물어봐야 할 것은 어떻게 특정 검색 패턴을 쿼리 할 수 ​​없게 만드는 것입니까? . 일으키는 원인이 WP_Query()결과가 없다고하는 것은 또는 그 질문에 대답하는 가장 좋은 방법이 될 수도 있고 그렇지 않을 수도 있습니다. 쿼리 할 수없는 검색 패턴설명 할 경우에도 도움이 될 수 있습니다 . 검색 패턴을 알면 솔루션을 찾아내는 데 도움이 될 수 있습니다.
Chip Bennett

답변:


28

시험

'post__in' => array(0)

간단하고 요점.


내 첫 번째 생각은-어딘가에 잘못되어야하지만 관련 코드를 감추면 실제로 실제로 잘 작동해야합니다. :)
Rarst

5
빈 배열은 최근 게시물을 반환하므로 0은 매우 중요합니다.
Mark Kaplun

감사! 이것은 post__in빈 배열을 전달했을 때 게시물을 반환 할 때 버그를 해결했습니다 ... array(0)훌륭하게 작동합니다! 이것은 이상하지만 실제로 WP 코어에서 버그로 나타난 문제를 추적 할 수는 있지만 너무 많은 테마 / 플러그인 개발자가 주변에 기능을 구축했기 때문에 그대로 남아 있습니다 -_- core.trac.wordpress.org/ ticket / 28099
EranSch

3

흥미롭게도 단락을위한 깨끗하고 명백한 방법은 없습니다 WP_Query.

주요 쿼리 인 경우 주변 WP->parse_request()에서 무언가를 해결할 수 있으며 비교적 최근 (3.5) do_parse_request필터가 있는 것 같습니다 .

그러나 WP_Query자체적으로 더러운 해킹은 필터 AND 1=0를 통해 추가하여 SQL 쿼리를 단락시키는 등의 순서로 이루어집니다 posts_where.


2
정보에 대해서 감사드립니다. 이차 루프 btw였습니다. 그리고 방금 "post_type" => "break_loop"존재하지 않는 게시물 유형 과 같은 더러운 해킹을 마쳤습니다 .
Brian

2

쿼리 매개 변수를 존재하지 않는 값으로 설정하는 문제는 2입니다.

  • 쿼리가 실행되므로 이미 결과가 없다는 것을 알고 있더라도 지불해야 할 성능 가격이 약간 있습니다
  • WordPress 쿼리에는 쿼리에 작용하는 19 개의 서로 다른 'posts_*'필터 후크 ( 'posts_where', 'post_join'등)가 있으므로 쿼리에 존재하지 않는 매개 변수를 설정해도 결과가 반환되지 않는다고 확신 할 수 없으며 OR필터에서 반환 하는 간단한 절이 무언가를 반환합니다.

쿼리가 결과를 반환하지 않고 (또는 매우 작은) 성능 문제 가 없는지 확인 하려면 약간의 하드 코어 루틴 이 필요합니다 .

해당 루틴을 트리거하기 위해 모든 메소드를 사용할 수 있으며 기술적으로 WP_Query존재하지 않는 이벤트 인수에 인수를 전달할 수 있습니다.

따라서와 같은 것을 좋아하면 다음과 같이 'force_no_results' => true사용할 수 있습니다.

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

'pre_get_posts'열심히 일하는 콜백을 추가하십시오 .

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

이 코드의 기능은 'pre_get_posts'가능한 한 늦게 실행됩니다 . 쿼리에 'force_no_results'인수가 있으면 다음을 수행하십시오.

  1. 먼저 쿼리를 방해 할 수있는 가능한 모든 필터를 제거하고 도우미 배열에 저장하십시오.
  2. 필터가 트리거되었는지 확인한 후 이러한 종류의 요청을 반환하는 필터를 추가하십시오. SELECT ID FROM wp_posts WHERE 0 = 1모든 필터가 제거되면이 쿼리가 변경 될 가능성이없고 매우 빠르며 결과가 확실하지 않습니다.
  3. 이 쿼리가 실행 된 직후 모든 원본 필터 (있는 경우)가 복원되고 모든 후속 쿼리가 예상대로 작동합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.