Проблеми щодо встановлення параметра запиту на неіснуюче значення: 2:
- Запит буде запущений, тому навіть якщо ви вже знаєте, що результатів не буде, потрібно заплатити невелику ціну продуктивності
- У WordPress-запитах є 19 різних
'posts_*'
гаків фільтрів ( 'posts_where'
, 'post_join'
і т. Д.), Які діють на запит, тому ви ніколи не можете бути впевнені, що навіть якщо встановити неіснуючий параметр, запит не поверне результатів, простий OR
пункт, повернутий фільтром, змусить щось повернути.
Вам потрібно трішки жорсткого розпорядження, щоб переконатися, що запит не повертає результату, і не виникає (або дуже мінімум) проблем з продуктивністю.
Щоб запустити цю процедуру, ви можете використовувати кожен метод, технічно ви можете передавати будь-який аргумент WP_Query
, аргументи події, яких не існує.
Тож якщо вам подобається щось подібне 'force_no_results' => true
, ви можете використовувати це так:
$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );
і додайте запущений зворотний дзвінок, 'pre_get_posts'
який виконує важку роботу:
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 );
Те, що робиться цим кодом, виконується 'pre_get_posts'
якомога пізніше. Якщо аргумент 'force_no_results' присутній у запиті, то:
- спочатку видаліть усі можливі фільтри, які можуть перешкоджати запиту, і збережіть їх у допоміжному масиві
- після переконайтеся, що фільтр спрацьовує, додайте фільтр adda, який повертає такий тип запиту:
SELECT ID FROM wp_posts WHERE 0 = 1
як тільки всі фільтри видалені, немає можливості, цей запит буде змінено, і він дуже швидкий, і не має результату напевно
- одразу після запуску цього запиту всі оригінальні фільтри (якщо такі були) відновлені, і всі наступні запити працюватимуть, як очікувалося.
WP_Query()
повернення результатів не може бути, а може бути і не найкращим способом відповісти на це питання. Це також може бути корисним, якщо ви опишете шаблон пошуку, який ви хочете отримати незрівнянним. Знання структури пошуку може допомогти вирішити рішення.