¿Puedo obligar a WP_Query a no devolver resultados?

20

Estoy trabajando en un sitio web con una función de búsqueda que permite a los usuarios buscar en una gran cantidad de mensajes meta. Hay un patrón de búsqueda específico al que me gustaría devolver por la fuerza ningún resultado. El WP_Query técnicamente encontrará resultados en la base de datos, pero me gustaría anularlo de alguna manera para forzarlo a que no devuelva resultados para activar el if( $example->have_posts() ) para fallar.

¿Hay algún tipo de parámetro que pueda pasar a WP_Query como 'force_no_results' => true que lo obligará a no dar resultados?

    
pregunta Brian 08.04.2014 - 22:01

3 respuestas

25

Probar

'post__in' => array(0)

Simple y al punto.

    
respondido por el David Labbe 09.04.2014 - 03:39
3

Curiosamente, no hay una forma limpia / explícita de cortocircuito WP_Query .

Si se trata de la consulta main , podrías resolver algo alrededor de WP->parse_request() , parece que hay un filtro relativamente reciente (3.5) do_parse_request allí.

Pero para WP_Query , los hacks sucios generalmente están en orden, como el cortocircuito de la consulta SQL al agregar AND 1=0 a través de posts_where filter, etc.

    
respondido por el Rarst 08.04.2014 - 22:46
2

Los problemas en establecer un parámetro de consulta en un valor inexistente son 2:

  • La consulta se ejecutará, por lo que incluso si ya sabe que no habrá resultados, hay un pequeño precio de rendimiento que pagar
  • Las consultas de WordPress tienen 19 ganchos de filtro 'posts_*' diferentes ( 'posts_where' , 'post_join' , etc.) que actúan sobre la consulta, por lo que nunca se puede estar seguro de que, al establecer un parámetro inexistente, la consulta no arroje resultados, una simple La cláusula OR devuelta por un filtro hace devolver algo.

Necesitas un poco de rutina hardcore para estar seguro de que la consulta no produce ningún resultado y no hay ningún problema de rendimiento (o muy mínimo).

Para activar esa rutina, puedes usar todos los métodos, técnicamente puedes pasar cualquier argumento a WP_Query , argumentos de evento que no existen.

Entonces, si te gusta algo como 'force_no_results' => true , puedes usarlo así:

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

y agregue una devolución de llamada que se ejecute en 'pre_get_posts' que haga el trabajo duro:

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

Lo que hace este código se ejecuta en 'pre_get_posts' lo más tarde posible. Si el argumento 'force_no_results' está presente en la consulta, entonces:

  1. primero elimine todos los filtros posibles que puedan interferir con la consulta y guárdelos dentro de una matriz de ayuda
  2. después de asegurarse de que se active el filtro, el filtro adda que devuelve este tipo de solicitud: SELECT ID FROM wp_posts WHERE 0 = 1 una vez que se eliminan todos los filtros, no hay posibilidades de que esta consulta cambie y sea muy rápida, y no tiene ningún resultado seguro / li>
  3. inmediatamente después de ejecutar esta consulta, todos los filtros originales (si hubiera alguno) se restaurarán y todas las consultas posteriores funcionarán como se esperaba.
respondido por el gmazzap 09.04.2014 - 05:26

Lea otras preguntas en las etiquetas