Добавление таксономии в поиск товаров: реализация и пример кода

Добавление таксономии (термина) в поиск постов

Задача

Необходимо добавить возможность поиска по названию атрибута товара в стандартный поиск продукта. Проще говоря, нужно, чтобы к стандартным результатам поиска товаров добавлялись товары, связанные с атрибутом "Производитель".

Логика работы

  • Поиск терминов в таксономии "Производитель" на основе запроса поиска.
  • Получение всех постов, связанных с найденными производителями.
  • Добавление найденных постов к общему пулу постов, найденных по умолчанию.

Этот механизм также можно использовать для поиска по любым типам постов и таксономиям — изменяйте код по своему усмотрению.

Пример кода

Вот пример того, как можно реализовать этот функционал:

// инициализация
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. Этот код можно адаптировать для других типов постов и таксономий, просто изменив его соответствующим образом.

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *