Добавляем название таксономии (термина) в поиск по записям
Задача: к стандартному поиску по товарам нужно добавить поиск и по названию атрибута товара. Другими словами нужно к дефолтному поиску товаров добавить товары, которые относятся к атрибуту "Производитель" из поисковой фразы.
Смотрите также: Добавляем поиск по метаполю в поиск по записям
Логика работы такая:
- Ищем в таксономии (атрибуте) "Производитель" термины по поисковой фразе
- Запрашиваем все записи, относящиеся к найденным производителям
- Добавляем найденные записи в общий пул записей, что были найдены стандартно
Данный механизм можно использовать и для поиска по любым типам записей и таксономиям - измените в коде их на желаемые.
// init
new Post_Search_With_Terms( [
'post_type' => 'product',
'taxonomy' => 'pa_izgotovitel'
] );
/**
* Extends default posts search in order to search by terms titles too.
*
* @version: 1.0
*/
final class Post_Search_With_Terms {
private $post_type;
private $taxonomy;
/**
* @param array $args {
* Arguments to retreive posts.
*
* @type string $post_type Default: post
* @type string $taxonomy Default: post_tag
* }
*/
public function __construct( $args = [] ) {
$args = (object) array_merge( [
'post_type' => 'post',
'taxonomy' => 'post_tag'
], $args );
foreach( $args as $key => $val ){
$this->$key = $val;
}
add_filter( 'pre_get_posts', [ $this, 'extends_search_query' ] );
}
/**
* @param WP_Query $wp_query
*/
public function extends_search_query( $wp_query ) {
// Только для основного запроса
if ( ! $wp_query->is_main_query() ) {
return;
}
// Только для указанного типа поста
if ( ! $wp_query->is_post_type_archive( $this->post_type ) ) {
return;
}
// Для поиска во фронте
if ( ! is_admin() && $wp_query->is_search() ) {
add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
}
// Для поиска в админке
if ( is_admin() ) {
add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
}
}
/**
* Возвращает термины указанной таксономии на основе поискового запроса.
*
* @return WP_Term[]|array Empty array if no terms found.
*/
private function search_terms() {
$search_query = filter_input( INPUT_GET, 's' );
if ( empty( $search_query ) ) {
return [];
}
$terms = get_terms( [
'taxonomy' => $this->taxonomy,
'name__like' => $search_query,
] );
return is_wp_error( $terms ) ? [] : $terms;
}
/**
* Добавляет в базовый запрос условия расширенной выборки по указанной таксономии.
*
* @param string $where
*
* @return string
*/
public function add_tax_query( $where ) {
global $wpdb;
$terms = $this->search_terms();
if ( $terms ) {
$ids = implode( ',', wp_list_pluck( $terms, 'term_id' ) );
$where .= " OR ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ($ids) )";
}
// Отменяем фильтр, чтобы он не применялся к другим запросам
remove_filter( 'posts_where', [ $this, __FUNCTION__ ] );
return $where;
}
}