Support

Account

Home Forums General Issues Adding custom fields search to WordPress search

Solved

Adding custom fields search to WordPress search

  • I have searched quite a lot for this fix but for the life of me can’t find it and wondered if anyone here could help?

    I am using Advanced Custom Fields 4.4.2 to store a list of business types for a particular Post (Customer). For each post a custom field called “business type” will have a number of values that can be selected i.e. Dr’s, Surgery, Doctors, First Aid etc.

    I would like to be able to include the “business-type” custom field in the search so that all posts (customers) that have this business type will show, alongside any post with that text in is also (which may not contain the custom field in it).

    I have tried using a function but I guess this turns the query into an “AND” statement rather than an “OR” (Join) statement.

    add_action(‘pre_get_posts’, ‘modify_post_search’);
    function modify_post_search($query)
    {
    if($query->is_search)
    {
    $query->set(‘meta_key’, ‘business_type’);
    $query->set(‘meta_value’, get_search_query());
    }
    }

    add_filter(‘pre_get_posts’, ‘filter_search’);
    ;

  • Hi John, I didn’t really want to use that plugin as it looked like it would lose control over a few things.

    So, I did another search today and this was worked first time. http://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

    Really handy as I just add it to the functions.php. It’s adding an JOIN to the query but I haven’t noticed much in the way of speed loss so I’m going with this.

  • I recommend Relevanssi for this. The advantage of using Relevanssi is that it pre-indexes your custom fields (and thus keeps your public searches up to speed).

    Use your imagination expanding the following code sample:

    
    function relevanssi_add_custom_fields( $fields )
    {
    	$fields = array(); // I like to start fresh
    	$fields[] = 'text_field';
    	$fields[] = 'people_0_firstname'; // meta key for 'firstname' field inside 'people' repeater.
    
    	$fields = implode( ',', $fields );
    
    	return $fields;
    }
    add_filter( 'option_relevanssi_index_fields', 'relevanssi_add_custom_fields' );
    
  • Hi EssexPaulo,

    Not sure if this is what you are after but have you tried by modifying your search.php file on your theme to something like this:

    
    <?php
    $customers = get_posts(array(
                                'post_type' => 'customers',
                                'posts_per_page' => -1,
                                'nopaging' => true,
                                'meta_query' => array(
                                    array(
                                        'key' => 'business_type',
                                        'value' => '"' . get_search_query()  . '"',
                                        'compare' => 'LIKE'
                                    )
                                )
                            ));
    
    ?>
    
    <?php /* Loop into the customers array and display the results */ ?>
    <?php foreach($customers as $customer_post) : ?>
    
       <?php /* Show your results */ ?>
       <?php setup_postdata($customer_post); ?>
    
    <?php endforeach; ?>
    
    <?php /* Keep standard search loop for any other posts */ ?>
    <?php while (have_posts()) : the_post(); ?>
    
      <?php /* Here remains the rest of the original search.php */ ?>
    
    <?php endwhile; ?>
    

    Cheers,

    Milton

  • Thanks for your help guys but the reply I put has sorted it very well. No bother with having to edit any files other than functions.php (which for a child theme is perfect)

    This was the link again http://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

    Thanks again for your help.
    Paul

  • Cool Find Paul,

    But maybe not everyone is to confident coding. There is a plugin FacetWP which is easy to configure and works well with Advanced Custom Fields.

  • If someone is looking for a solution to this problem is to recommend the plugin:
    https://wordpress.org/plugins/acf-better-search/

    This plugin adds to default WordPress search engine the ability to search by content from selected fields of Advanced Custom Fields plugin.

    Everything works automatically, no need to add any additional code.

  • For anyone else looking for a solution and doesn’t want to write code or download a third third party plugin, use this ACF add-on plugin: https://wordpress.org/plugins/acf-better-search/

    Cheers.

  • As this is article comes up a lot in search results, I wanted to add my experiences.

    I prefer coding to plugins whenever it makes sense. Without a plugin, I was not able to search both the post title and the ACF fields for a custom post type. Making changes to functions.php and/or creating a custom WP_Query, I just couldn’t get there.

    Using ACF: Better Search, I found it includes ACF fields on the search result page (search.php) but doesn’t work for custom post types (archive-my_post_type.php) or custom WP_Query.

    I installed Relevanssi and it offers a simple way to include post types and custom fields. I ran the index and it works perfectly for me.

  • In my case it’s not a custom post type, so that’s simpler. The code in https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/ works, but it includes media files in the results (matching image filename or title – I’m not sure). Is there a way to restrict the results to only posts?

    Even though, like ggeiger, I prefer code (cutting with a scalpel instead of a hatchet), I also tried ACF: Better Search. But it did even worse – it not only included media, but failed to even find posts that matched on a custom field I particularly care about, which happens to be structured as a taxonomy. Apparently that’s too hard for the plugin.

  • A taxonomy field only stores the term ID, it does not store the them name or any other information related to the term as part of post meta. If you want to search posts by term names then you need to copy the term name(s) to some post meta field when the post is updated so that it is available for searching. Either this or your custom search must include a taxonomy query and I’m not sure how you’d accomplish that.

  • Judging from the way Adam Balée’s code augments the SQL query, it appears that the term names are already in the post meta table. Here are the two PHP statements in his code that modify the query (they are in separate functions, but clearly end up in the same piece of SQL):

    $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';

    $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)", $where );
  • That is searching the post meta fields but it is not adding the term name to a meta field. There is nothing in that code that indicates to me that the term name has been added to post meta.

    You would need to create an acf/save_post action. In your function you would need to get the terms for the post or get the value from a taxonomy field if that is what you are using. Then you would need to use update_post_meta() to update/add the term name(s) to the post.

  • Yes, I know it’s not editing the database at all – I wouldn’t want it to. I just want it to find posts whose custom fields (including taxonomy terms) have a match to the search word. It does that successfully. The only thing I wish was different is that it lists not only posts but also media files, but I don’t want the media files to show up.

  • it works for me

    function custom_search_query( $query ) {
        if ( !is_admin() && $query->is_search ) {
    		$result = $query->query_vars['s'];
    		$query->query_vars['s'] = '';
            $query->set('meta_query', array('relation' => 'OR',
                array(
    				'key'     => 'acf_name', // ACF FIELD NAME OR POST META
    				'value'   => $result,
    				'compare' => 'LIKE',
                )
            ));
            $query->set('post_type', 'servicios'); // optional POST TYPE
        }
    }
    add_filter( 'pre_get_posts', 'custom_search_query');
    
  • @rocio1011 It works for you to do what? Your code connects to a different hook than the other code snippets discussed earlier, so I’m not sure I can tell what it does or how to try it for myself. Can you explain a little more?

  • Sorry. My English is bad. That code works only to search by custom fields.

    If you want to add custom fields to the search, then you need to use this.

    function cf_search_join( $join ) {
        global $wpdb;
    
        if ( is_search() ) {    
            $join .=' LEFT JOIN '.$wpdb->postmeta. ' cfmeta ON '. $wpdb->posts . '.ID = cfmeta.post_id ';
        }
    
        return $join;
    }
    add_filter('posts_join', 'cf_search_join' );
    
    function cf_search_where( $where ) {
        global $pagenow, $wpdb;
    
        if ( is_search() ) {
            $where = preg_replace(
                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
                "(".$wpdb->posts.".post_title LIKE $1) OR (cfmeta.meta_value LIKE $1)", $where );
        }
    
        return $where;
    }
    add_filter( 'posts_where', 'cf_search_where' );
    
    function cf_search_distinct( $where ) {
        global $wpdb;
    
        if ( is_search() ) {
            return "DISTINCT";
        }
    
        return $where;
    }
    add_filter( 'posts_distinct', 'cf_search_distinct' );
  • Sorry. My English is bad. That code works only to search by custom fields.

    If you want to add custom fields to the search, then you need to use this.

    function cf_search_join( $join ) {
        global $wpdb;
    
        if ( is_search() ) {    
            $join .=' LEFT JOIN '.$wpdb->postmeta. ' cfmeta ON '. $wpdb->posts . '.ID = cfmeta.post_id ';
        }
    
        return $join;
    }
    add_filter('posts_join', 'cf_search_join' );
    
    function cf_search_where( $where ) {
        global $pagenow, $wpdb;
    
        if ( is_search() ) {
            $where = preg_replace(
                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
                "(".$wpdb->posts.".post_title LIKE $1) OR (cfmeta.meta_value LIKE $1)", $where );
        }
    
        return $where;
    }
    add_filter( 'posts_where', 'cf_search_where' );
    
    function cf_search_distinct( $where ) {
        global $wpdb;
    
        if ( is_search() ) {
            return "DISTINCT";
        }

    return $where;
    }
    add_filter( ‘posts_distinct’, ‘cf_search_distinct’ );
    `

  • Sorry. My English is bad. That code works only to search by custom fields.

    If you want to add custom fields to the search, then you need to use this.

    
    function cf_search_join( $join ) {
        global $wpdb;
    
        if ( is_search() ) {    
            $join .=' LEFT JOIN '.$wpdb->postmeta. ' cfmeta ON '. $wpdb->posts . '.ID = cfmeta.post_id ';
        }
    
        return $join;
    }
    add_filter('posts_join', 'cf_search_join' );
    
    function cf_search_where( $where ) {
        global $pagenow, $wpdb;
    
        if ( is_search() ) {
            $where = preg_replace(
                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
                "(".$wpdb->posts.".post_title LIKE $1) OR (cfmeta.meta_value LIKE $1)", $where );
        }
    
        return $where;
    }
    add_filter( 'posts_where', 'cf_search_where' );
    
    function cf_search_distinct( $where ) {
        global $wpdb;
    
        if ( is_search() ) {
            return "DISTINCT";
        }
    
        return $where;
    }
    add_filter( 'posts_distinct', 'cf_search_distinct' );
    
  • (I have problems to insert code, I have commented like 4 times hahaha)
    Sorry. My English is bad. That code works only to search by custom fields.

    If you want to add custom fields to the search, then you need to use this.

  • function cf_search_join( $join ) {
        global $wpdb;
    
        if ( is_search() ) {    
            $join .=' LEFT JOIN '.$wpdb->postmeta. ' cfmeta ON '. $wpdb->posts . '.ID = cfmeta.post_id ';
        }
    
        return $join;
    }
    add_filter('posts_join', 'cf_search_join' );
    
    function cf_search_where( $where ) {
        global $pagenow, $wpdb;
    
        if ( is_search() ) {
            $where = preg_replace(
                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
                "(".$wpdb->posts.".post_title LIKE $1) OR (cfmeta.meta_value LIKE $1)", $where );
        }
    
        return $where;
    }
    add_filter( 'posts_where', 'cf_search_where' );
    
    function cf_search_distinct( $where ) {
        global $wpdb;
    
        if ( is_search() ) {
            return "DISTINCT";
        }
    
        return $where;
    }
    add_filter( 'posts_distinct', 'cf_search_distinct' );
  • Your English is fine. (But if you want help translating, I recommend https://www.deepl.com/translator) All your comments were posted! 🙂 You can probably keep the first one and delete the rest.

    The code you posted is exactly the same as what I’m using. But the search results include media items, not just posts. For example, see: https://japanharvest.org/?s=ellrick The first eight results are just images whose filename includes “ellrick”. I want to exclude media, but I don’t know how.

  • @rocio1011 but it’s possible to add only the selected custom field? Not all of them?

  • @agn_woj99 Are you desiring to include only one custom field in the search, or are you thinking that the code we’ve been talking about would only add one at a time? I’m not sure which you’re asking, but the code I’m using (which is the same as what rocio1011 posted several times) is from this page: https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/ (Be aware that you need to make a small change described in the last comment below the post to work with newer versions of WordPress.) This code causes the regular WordPress search to include custom fields, including even custom taxonomies, which was important for me. It includes all of them, not just one.

    I’m still hoping someone will come up with code that can exclude media from the search results, but that’s a different issue.

Viewing 25 posts - 1 through 25 (of 29 total)

The topic ‘Adding custom fields search to WordPress search’ is closed to new replies.