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?
Versuchen
'post__in' => array(0)
Einfach und auf den Punkt.
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.
Die Probleme beim Festlegen eines Abfrageparameters auf einen nicht vorhandenen Wert sind 2:
'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:
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