Добавление таксономии (термина) в поиск постов
Задача
Необходимо добавить возможность поиска по названию атрибута товара в стандартный поиск продукта. Проще говоря, нужно, чтобы к стандартным результатам поиска товаров добавлялись товары, связанные с атрибутом "Производитель".
Логика работы
- Поиск терминов в таксономии "Производитель" на основе запроса поиска.
- Получение всех постов, связанных с найденными производителями.
- Добавление найденных постов к общему пулу постов, найденных по умолчанию.
Этот механизм также можно использовать для поиска по любым типам постов и таксономиям — изменяйте код по своему усмотрению.
Пример кода
Вот пример того, как можно реализовать этот функционал:
// инициализация
new Post_Search_With_Terms( [
'post_type' => 'product',
'taxonomy' => 'pa_manufacturer'
] );
Класс для расширения поиска постов
/**
* Расширяет стандартный поиск постов, добавляя возможность поиска по названиям терминов.
*
* @version: 1.0
*/
final class Post_Search_With_Terms {
private $post_type;
private $taxonomy;
/**
* @param array $args {
* Аргументы для получения постов.
*
* @type string $post_type По умолчанию: post
* @type string $taxonomy По умолчанию: 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 Пустой массив, если термины не найдены.
*/
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;
}
}
Заключение
Теперь вы знаете, как добавить возможность поиска по атрибуту "Производитель" в стандартный поиск товаров WordPress. Этот код можно адаптировать для других типов постов и таксономий, просто изменив его соответствующим образом.