it-swarm.com.de

Kann ich WP_Query zwingen, keine Ergebnisse zurückzugeben?

Ich arbeite an einer Website mit einer Suchfunktion, mit der Benutzer viele Post-Metas durchsuchen können. Es gibt ein bestimmtes Suchmuster, für das ich keine Ergebnisse erzwingen möchte. Die WP_Query findet technisch gesehen Ergebnisse in der Datenbank, aber ich würde das gerne überschreiben, um sie dazu zu zwingen, keine Ergebnisse zurückzugeben, damit die if( $example->have_posts() ) fehlschlägt.

Gibt es eine Art Parameter, den ich an WP_Query übergeben kann, z. B. 'force_no_results' => true, durch den er gezwungen wird, keine Ergebnisse zurückzugeben?

21
Brian

Versuchen

'post__in' => array(0)

Einfach und auf den Punkt.

26
David Labbe

Seltsamerweise gibt es keinen sauberen/expliziten Weg, WP_Query kurzzuschließen.

Wenn es sich um main query handelt, könnten Sie etwas über WP->parse_request() herausfinden, da scheint es einen relativ neuen (3.5) do_parse_request-Filter zu geben.

Aber für WP_Query selbst sind schmutzige Hacks normalerweise in Ordnung, wie das Kurzschließen von SQL-Abfragen durch Hinzufügen von AND 1=0 über den posts_where-Filter usw.

3
Rarst

Die Probleme beim Festlegen eines Abfrageparameters auf einen nicht vorhandenen Wert sind 2:

  • Die Abfrage wird ausgeführt, sodass auch wenn Sie bereits wissen, dass keine Ergebnisse vorliegen, ein geringer Leistungspreis zu zahlen ist
  • In WordPress-Abfragen gibt es 19 verschiedene 'posts_*'-Filter-Hooks ('posts_where', 'post_join' usw.), die auf Abfragen einwirken. Sie können also nie sicher sein, dass selbst bei nicht vorhandenen Parametern keine Ergebnisse zurückgegeben werden. Eine einfache OR -Klausel wird von a zurückgegeben Filter machen etwas zurück.

Sie benötigen ein wenig hardcore routine, um sicher zu sein dass eine Abfrage kein Ergebnis zurückgibt und es kein (oder ein sehr geringes) Leistungsproblem gibt.

Um diese Routine auszulösen, können Sie jede Methode verwenden. Technisch gesehen können Sie jedes Argument an WP_Query übergeben, Ereignisargumente, die nicht vorhanden sind.

Wenn Sie also etwas wie 'force_no_results' => true mögen, können Sie es so verwenden:

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

und fügen Sie einen Rückruf hinzu, der auf 'pre_get_posts' ausgeführt wird und die harte Arbeit leistet:

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

Was dieser Code tut, wird so spät wie möglich auf 'pre_get_posts' ausgeführt. Wenn das Argument 'force_no_results' in der Abfrage vorhanden ist, gilt Folgendes:

  1. entfernen Sie zunächst alle möglichen Filter, die die Abfrage beeinträchtigen können, und speichern Sie sie in einem Hilfsarray
  2. nachdem Sie sicher sind, dass der Filter ausgelöst wurde, fügen Sie einen Filter hinzu, der diese Art von Anforderung zurückgibt: SELECT ID FROM wp_posts WHERE 0 = 1 Sobald alle Filter entfernt wurden, gibt es keine Möglichkeiten, diese Abfrage zu ändern. Sie ist sehr schnell und hat mit Sicherheit kein Ergebnis
  3. unmittelbar nachdem diese Abfrage ausgeführt wurde, werden alle ursprünglichen Filter (sofern vorhanden) wiederhergestellt und alle nachfolgenden Abfragen funktionieren wie erwartet.
2
gmazzap