Posso forçar o WP_Query a não retornar nenhum resultado?

20

Estou trabalhando em um site com um recurso de pesquisa que permite aos usuários pesquisar em muitas postagens. Existe um padrão de pesquisa específico para o qual gostaria de não retornar resultados forçados. O WP_Query tecnicamente encontrará resultados no banco de dados, mas gostaria de substituir isso de alguma forma para forçá-lo a não retornar nenhum resultado para acionar o if( $example->have_posts() ) para falhar.

Existe algum parâmetro que eu possa passar para WP_Query como 'force_no_results' => true , que irá forçá-lo a não retornar nenhum resultado?

    
por Brian 08.04.2014 / 22:01

3 respostas

25

Tente

'post__in' => array(0)

Simples e direto ao ponto.

    
por David Labbe 09.04.2014 / 03:39
3

Curiosamente, não há maneira limpa / explícita de causar curto-circuito WP_Query .

Se for uma consulta main , você pode resolver algo em torno de WP->parse_request() , parece haver um filtrodo_parse_request relativamente recente (3.5)%.

Mas para WP_Query os hacks sujos geralmente estão em ordem, como um curto-circuito na consulta SQL, adicionando AND 1=0 via posts_where filter, etc.

    
por Rarst 08.04.2014 / 22:46
2

Os problemas em definir um parâmetro de consulta para um valor inexistente são 2:

  • A consulta será executada, por isso, mesmo que você já saiba que não haverá resultados, haverá um pequeno preço por desempenho a pagar
  • As consultas do WordPress têm 19% diferentes ganchos de filtro 'posts_*' ( 'posts_where' , 'post_join' , etc.) que agem na consulta, portanto você nunca pode ter certeza de que mesmo definindo parâmetros inexistentes, a consulta não retorna resultados, um simples A cláusula OR retornada por um filtro faz com que algo seja retornado.

Você precisa de uma pequena rotina hardcore para ter certeza de que uma consulta não retorne nenhum resultado e não haja (ou muito pouco) problema de desempenho.

Para acionar essa rotina, você pode usar todos os métodos, tecnicamente você pode passar qualquer argumento para WP_Query , argumentos de eventos que não existem.

Então, se você gosta de algo como 'force_no_results' => true , pode usá-lo da seguinte forma:

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

e adicione um retorno de chamada em execução no 'pre_get_posts' que faz o trabalho pesado:

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

O que esse código faz é executado em 'pre_get_posts' o mais tarde possível. Se o argumento 'force_no_results' estiver presente na consulta, então:

  1. primeiro remova todos os filtros possíveis que possam interferir na consulta e armazene-os em uma matriz auxiliar
  2. depois de ter certeza de que o filtro é acionado, filtro adda que retorna esse tipo de solicitação: SELECT ID FROM wp_posts WHERE 0 = 1 assim que todos os filtros forem removidos, não há possibilidade de que essa consulta seja alterada e seja muito rápida e não tenha resultado
  3. imediatamente após a execução dessa consulta, todos os filtros originais (se houver algum) serão restaurados e todas as consultas subsequentes funcionarão conforme o esperado.
por gmazzap 09.04.2014 / 05:26