0

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,

1

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' );
  • Thanks Krzysiek, that's worked a treat. I also have another use case where I use the s arg in WP_Query for an ajax product search specifically, the above search code doesn't seem to have any affect on that. Does WP_Querys implementation differ? – Jam3sn Feb 27 at 17:30
  • Answered here: wordpress.stackexchange.com/questions/330346/… – Jam3sn Mar 1 at 12:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.