3

I need to add custom field to wordpress search result.

This what i tried to do is used pre_get_posts filter, like this:

function search_filter( $query ) {

    $key_fields = array ( 'buty' );
    $value_field = $query->query_vars['s'];
    $query->query_vars['s'] = '';

    if ( $value_field != '' ) {

        $filter_query = array( 'relation' => 'OR' );

        foreach ( $key_fields as $one_field ) {
            array_push ( $filter_query , array (
                'key' => $one_field,
                'value' => $value_field,
                'compare' => 'LIKE'
            ) );
        }
        $query->set( 'meta_query' , $filter_query );

    }

}
add_filter( 'pre_get_posts' , 'search_filter');

It works, but now search not working for post title and post content

So the question is: how to properly add custom field to Wordpress search result without lose standard functionality?

4
  • What exactly do you mean by "add custom field to search result"? Could you add some examples to your question? Jul 28, 2018 at 15:55
  • Of course - for example i have custom field with key 'Shoes' and value is 'Adidas'. Now i would like type in website search form 'Adidas' and in the search results I would like to see posts that contain this field
    – kanlukasz
    Jul 28, 2018 at 16:01
  • How many custom fields do you have? Jul 28, 2018 at 16:02
  • Let us assume that I only have one field
    – kanlukasz
    May 21, 2021 at 8:34

1 Answer 1

4

Wordpress search in posts table. You must change the search query by adding a postmeta table (with LEFT JOIN) and then add your own conditions to WHERE clause.

<?php
/**
 * Extend WordPress search to include custom fields
 *
 * https://adambalee.com
 */

/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    return $join;
}
add_filter('posts_join', 'cf_search_join' );

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    $key_fields = array ( 'buty' );
    if ( is_search() ) 
        $where = preg_replace(
            "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(".$wpdb->posts.".post_title LIKE $1) OR ("
                 .$wpdb->postmeta. ".meta_value LIKE $1 AND "
                 .$wpdb->postmeta. ".meta_key IN ('" .implode("','", $key_fields). "') )", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );

Details can be found here "Search WordPress by Custom Fields without a Plugin"

4
  • One question for sure - Is it secure to use this modified where SQL, without prepared statement or any escaped?
    – kanlukasz
    May 29, 2019 at 9:12
  • 1
    $where SQL was prepared earlier, here you only copy part of it (after LIKE) and use it with another column. The only new thing added to the query are values from $key_fields. In this case, there is no need to escape these values, because they are known to you and do not change. If, for example, the value of the $key_fields would be the result of the function or it would be passed to the filter (apply_filters), then it would be good to use $wpdb->prepare() to secure the SQL statement.
    – nmr
    May 29, 2019 at 9:48
  • This doesn't seem to work in current WordPress @nmr, any chance of revising ?
    – AdamJones
    Dec 12, 2019 at 13:29
  • @AdamJones I just checked the above code in WordPress v4.8, v5.2, v5.3 and it worked with each of them. Maybe it works differently than you expected with a multi-word search phrase.
    – nmr
    Dec 13, 2019 at 23:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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