Adding taxonomy (term) to post search
Task: To the standard product search, it is necessary to add search by the product attribute name. In other words, it is necessary to add products related to the "Manufacturer" attribute to the default product search results.
The logic is as follows:
- Search for terms in the "Manufacturer" taxonomy based on the search query
- Retrieve all posts related to the found manufacturers
- Add the retrieved posts to the overall pool of posts that were found by default
This mechanism can also be used for searching any types of posts and taxonomies - modify them in the code as desired.
// init new Post_Search_With_Terms( [ 'post_type' => 'product', 'taxonomy' => 'pa_manufacturer' ] ); /** * 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 retrieve 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 ) { // Only for the main query if ( ! $wp_query->is_main_query() ) { return; } // Only for the specified post type if ( ! $wp_query->is_post_type_archive( $this->post_type ) ) { return; } // For front-end search if ( ! is_admin() && $wp_query->is_search() ) { add_filter( 'posts_where', [ $this, 'add_tax_query' ] ); } // For admin search if ( is_admin() ) { add_filter( 'posts_where', [ $this, 'add_tax_query' ] ); } } /** * Returns terms of the specified taxonomy based on the search 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; } /** * Adds conditions for extended selection by the specified taxonomy to the base query. * * @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 the filter so it does not apply to other queries remove_filter( 'posts_where', [ $this, __FUNCTION__ ] ); return $where; } }