I'm trying to add to the WP search so it includes some meta fields. Here's my current code in the functions.php
which was based of another stack from a few years back:
function extend_search_query($query) {
if ($query->is_search) {
$query->set('meta_query', [
'relation' => 'OR',
[
'key' => 'ean',
'value' => filter_var($query->query_vars['s'], FILTER_SANITIZE_STRING),
'compare' => 'LIKE',
],[
'key' => 'product_code',
'value' => filter_var($query->query_vars['s'], FILTER_SANITIZE_STRING),
'compare' => 'LIKE',
]
]);
};
}
add_filter('pre_get_posts', 'extend_search_query');
When doing this, the search returns no results for any kind of search. Essentially, I just want this fields to also be check like the post title and content etc.
I did try adding it to the WP_Query on the search page as a meta_query
in the args, but again found this messed with the search.
Thanks,
I'm trying to add to the WP search so it includes some meta fields. Here's my current code in the functions.php
which was based of another stack from a few years back:
function extend_search_query($query) {
if ($query->is_search) {
$query->set('meta_query', [
'relation' => 'OR',
[
'key' => 'ean',
'value' => filter_var($query->query_vars['s'], FILTER_SANITIZE_STRING),
'compare' => 'LIKE',
],[
'key' => 'product_code',
'value' => filter_var($query->query_vars['s'], FILTER_SANITIZE_STRING),
'compare' => 'LIKE',
]
]);
};
}
add_filter('pre_get_posts', 'extend_search_query');
When doing this, the search returns no results for any kind of search. Essentially, I just want this fields to also be check like the post title and content etc.
I did try adding it to the WP_Query on the search page as a meta_query
in the args, but again found this messed with the search.
Thanks,
There is one problem with your query. You assume, that it will use OR
relation to all query parts. But it won't. The OR operator will be used only for meta_query parts.
It means, that your query is looking for posts that are matching these criteria:
(post_title LIKE query) AND ( ean LIKE query OR product_code LIKE query )
So if you'll search for EAN, then no results will be found, because no product have EAN in its title. And if you'll search for any word, then it also won't return any results, because no product will have that word in EAN or product_code field.
So is it possible to search like that? And how to?
Yes, it is. One way of doing it is adding these filters:
function search_by_meta_join( $join ) {
global $wpdb;
if ( is_search() ) {
$join .= " LEFT JOIN {$wpdb->postmeta} pm_ean ON {$wpdb->posts}.ID = pm_ean.post_id AND (pm_ean.meta_key = 'ean') ";
$join .= " LEFT JOIN {$wpdb->postmeta} pm_code ON {$wpdb->posts}.ID = pm_code.post_id AND (pm_code.meta_key = 'product_code') ";
}
return $join;
}
add_filter('posts_join', 'search_by_meta_join' );
function search_by_meta_where( $where ) {
global $wpdb;
if ( is_search() ) {
$where = preg_replace(
"/\(\s*{$wpdb->posts}.post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"({$wpdb->posts}.post_title LIKE $1) OR (pm_ean.meta_value LIKE $1) OR (pm_code.meta_value LIKE $1) ", $where );
}
return $where;
}
add_filter( 'posts_where', 'search_by_meta_where' );