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 Preis für die Leistung 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 eine einfache OR
Klausel, die von einem Filter zurückgegeben wird, etwas zurückgibt, wenn Sie nicht vorhandene Parameter für die Abfrage zurückgeben .
Sie benötigen ein wenig Hardcore- Routine, um sicherzustellen , dass eine Abfrage kein Ergebnis zurückgibt und kein (oder nur sehr geringfügiges) Leistungsproblem vorliegt.
Um diese Routine auszulösen, können Sie jede Methode verwenden. Technisch gesehen können Sie jedes Argument an WP_Query
Ereignisargumente übergeben, das nicht vorhanden ist.
Wenn Ihnen also etwas gefällt 'force_no_results' => true
, können Sie es folgendermaßen verwenden:
$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );
und fügen Sie einen Rückruf hinzu, der ausgeführt wird und 'pre_get_posts'
die harte Arbeit erledigt :
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 'pre_get_posts'
so spät wie möglich ausgeführt. Wenn das Argument 'force_no_results' in der Abfrage vorhanden ist, gilt Folgendes:
- Entfernen Sie zunächst alle möglichen Filter, die die Abfrage beeinträchtigen können, und speichern Sie sie in einem Hilfsarray
- 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
Wenn alle Filter entfernt wurden, gibt es keine Möglichkeiten, diese Abfrage zu ändern. Sie ist sehr schnell und hat mit Sicherheit kein Ergebnis
- Unmittelbar nachdem diese Abfrage ausgeführt wurde, werden alle ursprünglichen Filter (sofern vorhanden) wiederhergestellt und alle nachfolgenden Abfragen funktionieren wie erwartet.
WP_Query()
Zurückgeben von Ergebnissen kann der beste Weg sein, diese Frage zu beantworten. Es kann auch hilfreich sein, wenn Sie das Suchmuster beschreiben , das Sie nicht abfragen möchten. Wenn Sie das Suchmuster kennen, können Sie möglicherweise eine Lösung finden.