Использование pre_get_posts для переопределения поискового запроса с отображением записей из нескольких таксономий
Казалось бы, это должно быть просто, но я застрял на этом!
Если пользователь ищет 'alice', я хочу показать ему все записи с терминами пользовательских таксономий 'bob' и 'carol', независимо от того, содержат ли эти записи строку 'alice' или нет.
Я могу установить tax_query в запросе, чтобы показывались только записи с терминами 'bob' и 'carol', но не могу сбросить сам поисковый запрос, чтобы показывались все записи, а не только те, которые содержат 'alice'.
Вот фильтр, который я использую для изменения tax_query:
if ( !$query->is_search )
return $query;
$taxquery = array(
'relation' => 'OR',
array(
'taxonomy' => 'people',
'field' => 'slug',
'terms' => array( 'bob' ),
),
array(
'taxonomy' => 'people',
'field' => 'slug',
'terms' => array( 'carol' ),
)
);
$query->set( 'tax_query', $taxquery );
return $query;
Но попытка установить поисковый запрос таким образом не работает:
$queryvars = array(
's' => ''
);
$query->set( 'query_vars', $queryvars );

Это не работает, потому что нельзя использовать set
для изменения всех параметров запроса. Самый простой способ — установить параметр 's'
в пустую строку:
add_action( 'pre_get_posts', function( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$taxquery = array( ... );
$query->set( 'tax_query', $taxquery );
$query->set('s', '' );
}
});
Таким образом, WordPress по-прежнему будет считать запрос поисковым, поэтому для отображения результатов будет использоваться шаблон search.php
, а при вызове is_search()
будет возвращаться TRUE
.
Если нужно, чтобы WordPress больше не считал запрос поисковым, необходимо также вручную удалить $query->query_vars['s']
и установить $query->is_search
в false:
add_action( 'pre_get_posts', function( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$taxquery = array( ... );
$query->set( 'tax_query', $taxquery );
$query->set('s', '' );
unset( $query->query['s'] );
$query->is_search = FALSE;
}
});
После этого WordPress больше не будет считать запрос поисковым и будет использовать шаблон index.php
.
Если нужно использовать другой шаблон, например taxonomy.php
, следует применить фильтр 'template_include'
:
add_action( 'pre_get_posts', function( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$taxquery = array( ... );
$query->set( 'tax_query', $taxquery );
$query->set('s', '' );
unset( $query->query['s'] );
$query->is_search = FALSE;
add_filter( 'template_include', function() {
return locate_template( 'taxonomy.php' )
}, 0 );
}
});
