Support

Account

Home Forums ACF PRO Fix: Include ACF fields content in WP Search

Solving

Fix: Include ACF fields content in WP Search

  • Hi,

    just wanted to share something, in case someone runs into the same problem. I needed a way to include the content of several acf fields into my normal WP search. I came up with the following solution:

    function advanced_custom_search( $where, &$wp_query ) {
    
        global $wpdb;
     
        if ( empty( $where )){
            return $where;
        }
     
        // get search expression
        $terms = $wp_query->query_vars[ 's' ];
    
        
        // explode search expression to get search terms
        $exploded = explode( ' ', $terms );
        if( $exploded === FALSE || count( $exploded ) == 0 )
            $exploded = array( 0 => $terms );
             
        // reset search in order to rebuilt it as we whish
        $where = '';
        
        // get searcheable_acf, a list of advanced custom fields you want to search content in
        $list_searcheable_acf = list_searcheable_acf();
    
        foreach( $exploded as $tag ) :
            $where .= " 
              AND (
                (".$wpdb->prefix."posts.post_title LIKE '%$tag%')
                OR (".$wpdb->prefix."posts.post_content LIKE '%$tag%')
                OR EXISTS (
                  SELECT * FROM ".$wpdb->prefix."postmeta
    	              WHERE post_id = ".$wpdb->prefix."posts.ID
    	                AND (";
    
            foreach ($list_searcheable_acf as $searcheable_acf) :
              if ($searcheable_acf == $list_searcheable_acf[0]):
                $where .= " (meta_key LIKE '%" . $searcheable_acf . "%' AND meta_value LIKE '%$tag%') ";
              else :
                $where .= " OR (meta_key LIKE '%" . $searcheable_acf . "%' AND meta_value LIKE '%$tag%') ";
              endif;
            endforeach;
    
    	        $where .= ")
                )
                OR EXISTS (
                  SELECT * FROM ".$wpdb->prefix."comments
                  WHERE comment_post_ID = ".$wpdb->prefix."posts.ID
                    AND comment_content LIKE '%$tag%'
                )
                OR EXISTS (
                  SELECT * FROM ".$wpdb->prefix."terms
                  INNER JOIN ".$wpdb->prefix."term_taxonomy
                    ON ".$wpdb->prefix."term_taxonomy.term_id = ".$wpdb->prefix."terms.term_id
                  INNER JOIN ".$wpdb->prefix."term_relationships
                    ON ".$wpdb->prefix."term_relationships.term_taxonomy_id = ".$wpdb->prefix."term_taxonomy.term_taxonomy_id
                  WHERE (
              		taxonomy = 'post_tag'
                		OR taxonomy = 'category'          		
                		OR taxonomy = 'myCustomTax'
              		)
                  	AND object_id = ".$wpdb->prefix."posts.ID
                  	AND ".$wpdb->prefix."terms.name LIKE '%$tag%'
                )
            )";
        endforeach;
        return $where;
    }
     
    add_filter( 'posts_search', 'advanced_custom_search', 500, 2 );
    
    function list_searcheable_acf(){
      $list_searcheable_acf = array('my_field','my_second_field','my_third_field'); // add acf field_names that you want to search through
      return $list_searcheable_acf;
    }
    

    This works like a charm for me and I do not need an additional plugin like relevanssi. Hope this is usefull for someone!

  • Hi @sixtyseven

    Thank you for the tip! It’s great to see people sharing what they’ve learned! 🙂

    I’m not sure why you wouldn’t want to use a search-enhancing plugin like relevanssi or searchWP? They provide quite a bit more than just the ability to search meta etc. such as fuzzy matching and stopwords to name a few.

    I’m always using a search-plugin for any site that utilise search.

  • Hi @sixtyseven,

    First of all, thanks a lot for the tip.
    Second : does your method work with repeaters ?

    Thanks

  • @marvinlerouge: The enhanced database query searchs for post meta keys, that have the searchphrase as a value. As far as I can see, this would work with repeater fields as well:

    $where .= " (meta_key LIKE '%" . $searcheable_acf . "%' AND meta_value LIKE '%$tag%') ";

    let’s assume you have a repeater named ‘my_field’. In the Database, you will find entries like my_field_0_repeaterfieldname, my_field_1_repeaterfieldname, etc. So if you add either ‘my_field’ or ‘repeaterfieldname’ to the $list_searcheable_acf array, the above query will resolve i.e. to:

    $where .= " (meta_key LIKE '%myfield%' AND meta_value LIKE '%$searchphrase%') ";

    But as I stated before, I am by no means a real coder 😉

  • @sixtyseven : One big problem with this way is that, if you have numerous fields, the query can becomme reaaaallly complex. So i took it another way :

    • i created one more field (let’s call it searchable)
    • you can also create a blacklist to ignore some fields
    • this field is populated on post_save : you get all the fields you want, clean it, and then use update_field
    • you can then use a single meta field in your search query (which is more or less the same one as you)

    Pros :

    • simple searchable meta, usable whatever the structure of the post type is
    • simple sql query
    • customizable for any post type via a blacklist loated in one place for any post type

    Cons :

    • clearly duplicated databse content, but we’re talking about sanitized text, and i really think that’s worth the price
    function save_searchable_content_meta($post_id, $post, $update) {
        $fields = get_fields($post->ID);
        if (array_key_exists("searchable_content", $fields)) {
    	    unset($fields["searchable_content"]);
    	    array_unshift($fields, $post->post_title, $post->post_content);
    	    $str = sanitize_text_field(array_to_str($fields));
    	    update_field("searchable_content", $str, $post_id);
    	}
    }
    add_action('save_post', 'save_searchable_content_meta', 10, 3);
    
  • 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.

  • Does your code work only with ACF Pro or with the free version as well?

Viewing 7 posts - 1 through 7 (of 7 total)

The topic ‘Fix: Include ACF fields content in WP Search’ is closed to new replies.