Posso forzare WP_Query a non restituire risultati?


23

Sto lavorando su un sito Web con una funzione di ricerca che consente agli utenti di cercare in molti post meta. Esiste un modello di ricerca specifico per il quale non vorrei restituire forzatamente risultati. WP_Query troverà tecnicamente risultati nel database, ma mi piacerebbe sovrascriverlo in qualche modo per costringerlo a non restituire risultati per innescare il if( $example->have_posts() )fallimento.

Esiste una sorta di parametro che posso passare a WP_Query in 'force_no_results' => truequesto modo lo costringerà a non restituire risultati?


1
Sembra che tu stia chiedendo un'implementazione già determinata, piuttosto che chiedere come risolvere il problema di root. Leggendo tra le righe, penso che ciò che dovresti davvero chiedere è: come posso rendere inammissibile uno specifico modello di ricerca? . Causare WP_Query()di non restituire risultati può o meno essere il modo migliore per rispondere a questa domanda. Potrebbe anche essere utile se descrivi il modello di ricerca che desideri non sia interrogabile. Conoscere il modello di ricerca potrebbe aiutare a scovare una soluzione.
Chip Bennett,

Risposte:


28

Provare

'post__in' => array(0)

Semplice e al punto.


Il mio primo pensiero è stato: questo deve andare storto da qualche parte, ma dallo sfogliare il codice correlato dovrebbe funzionare piuttosto bene. :)
Rarst

5
lo zero è molto importante in quanto solo un array vuoto restituirà i post recenti.
Mark Kaplun,

Grazie! Questo ha risolto un bug per me mentre post__inrestituivo i post quando veniva passato un array vuoto ... array(0)funziona benissimo! Questo è strano ma in realtà può essere ricondotto a un problema che si presentava nel core di WP come un bug, ma è stato lasciato così com'è perché troppi sviluppatori di temi / plug-in hanno costruito funzionalità attorno ad esso -_- core.trac.wordpress.org/ biglietto / 28099
EranSch

3

Curiosamente non esiste un modo pulito / esplicito per il corto circuito WP_Query.

Se è la query principale su cui potresti risolvere qualcosa WP->parse_request(), sembra che ci sia un do_parse_requestfiltro (3.5) relativamente recente .

Ma per WP_Querysé gli hack sporchi sono di solito in ordine, come il cortocircuito della query SQL aggiungendo AND 1=0tramite posts_wherefiltro, ecc.


2
Grazie per le informazioni. Era un ciclo secondario tra l'altro. E ho appena finito per fare un trucco sporco come "post_type" => "break_loop"un tipo di post inesistente.
Brian,

2

I problemi relativi all'impostazione di un parametro di query su un valore inesistente sono 2:

  • La query verrà eseguita, quindi anche se sai già che non ci saranno risultati, c'è un piccolo prezzo di rendimento da pagare
  • Le query di WordPress hanno 19 diversi 'posts_*'hook di filtro ( 'posts_where', 'post_join'ecc.) Che agiscono sulla query, quindi non si può mai essere sicuri che anche impostando parametri inesistenti la query non restituisca risultati, una semplice ORclausola restituita da un filtro fa restituire qualcosa.

Avete bisogno di un po ' hard di routine per essere sicuri di una query restituire alcun risultato e non c'è (o molto minimun) problema di prestazioni.

Per attivare quella routine, è possibile utilizzare ogni metodo, tecnicamente è possibile passare qualsiasi argomento WP_Query, argomenti evento che non esiste.

Quindi, se ti piace qualcosa del genere 'force_no_results' => true, puoi usarlo in questo modo:

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

e aggiungi un callback in esecuzione 'pre_get_posts'che faccia il duro lavoro:

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

Ciò che fa questo codice viene eseguito il 'pre_get_posts'più tardi possibile. Se l'argomento 'force_no_results' è presente nella query, allora:

  1. rimuovere innanzitutto tutti i possibili filtri che possono interferire con la query e archiviarli in un array di helper
  2. dopo esserti assicurato che il filtro sia attivato, aggiungi un filtro che restituisca questo tipo di richiesta: SELECT ID FROM wp_posts WHERE 0 = 1una volta rimossi tutti i filtri, non c'è possibilità che questa query venga modificata ed è molto veloce e non ha alcun risultato certo
  3. immediatamente dopo l'esecuzione di questa query, tutti i filtri originali (se presenti) vengono ripristinati e tutte le query successive funzioneranno come previsto.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.