Problemy z ustawieniem parametru zapytania na nieistniejącą wartość to 2:
- Zapytanie zostanie uruchomione, więc nawet jeśli już wiesz, że nie będzie wyników, musisz zapłacić niewielką cenę za wydajność
- Zapytania WordPress mają 19 różnych
'posts_*'
zaczepów filtrów ( 'posts_where'
, 'post_join'
itp.), Które działają na zapytania, więc nigdy nie możesz być pewien, że nawet ustawienie nieistniejącego parametru zapytania nie zwróci żadnych wyników, prosta OR
klauzula zwrócona przez filtr sprawi, że coś zwróci.
Potrzebujesz trochę hardcorowej rutyny, aby mieć pewność, że zapytanie nie zwróci żadnego wyniku i nie wystąpi (lub będzie bardzo minimalny) problem z wydajnością.
Aby uruchomić tę procedurę, możesz użyć każdej metody, technicznie możesz przekazać dowolny argument WP_Query
, argumenty zdarzenia, które nie istnieją.
Więc jeśli lubisz coś takiego 'force_no_results' => true
, możesz użyć tego w następujący sposób:
$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );
i dodaj wywołanie zwrotne działające na nim 'pre_get_posts'
, wykonując ciężką pracę:
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 );
To, co robi ten kod, jest uruchamiane 'pre_get_posts'
tak późno, jak to możliwe. Jeśli w zapytaniu występuje argument „force_no_results”, wówczas:
- najpierw usuń wszystkie możliwe filtry, które mogą zakłócać zapytanie, i zapisz je w tablicy pomocniczej
- po upewnieniu się, że filtr jest uruchomiony, dodaj filtr, który zwraca takie żądanie:
SELECT ID FROM wp_posts WHERE 0 = 1
po usunięciu wszystkich filtrów nie ma możliwości zmiany tego zapytania i jest ono bardzo szybkie i na pewno nie ma żadnego wyniku
- natychmiast po uruchomieniu tego zapytania przywracane są wszystkie oryginalne filtry (jeśli takie istniały), a wszystkie kolejne zapytania działają zgodnie z oczekiwaniami.
WP_Query()
braku wyników może, ale nie musi być najlepszym sposobem na udzielenie odpowiedzi na to pytanie. Pomocne może być również opisanie wzorca wyszukiwania, którego nie można zapytać. Znajomość wzorca wyszukiwania może pomóc w znalezieniu rozwiązania.