Enable Custom Field Searching With Wordpress 2.6

I have previously talked about enable custom field search in Wordpress, but that involved altering the main Wordpress files, which is a big no-no.

So is there an alternative? Well, yes, otherwise I wouldn't have bothered writing the post! To enable custom field (also called Wordpress metadata) searching you need to set up two things.

First you need to have created a custom field (or two) and added this to a number of posts.

Next, you need to have a custom search form that has the name of the field set as the name of an input box. You don't even need the normal s input box that Wordpress uses as default.

Open up your template functions.php file and add in the following three lines of code.

1
2
3
add_filter('posts_join','search_metadata_join');
add_filter('posts_where','search_metadata');
add_filter('posts_groupby','search_meta_groupby');

This adds three callback filters to Wordpress at run time. The posts_join will add the meta table into our query so that we can work with it. The posts_where will be the main function where all of our where clauses will be build. Finally, posts_groupby will stop multiple posts appearing for the same term. All we have to do now is include the queries we need in order to enable custom field searching. I will do each of the callback functions in the order they appeared above.

1
2
3
4
5
6
7
8
9
10
11
function search_metadata_join($join) {
  global $wp_query, $wpdb, $wp_version;
   // add in check for older versions
  if($wp_version >= '2.3'){
    $join .= " LEFT JOIN $wpdb->postmeta AS m ON ($wpdb->posts.ID = m.post_id) ";
  }else{
    $join .= "LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
  }
  
  return $join;
}

The search_metadata() function has a array variable called $metaVars. This contains an array of the names of the custom fields that you want to search through. Each item in the array is checked to see if it has a value, and if it does it is included in a string called clause. The function is set up to allow for any of the custom fields being true, which is what I wanted it do to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function search_metadata($where) {
  global $wp_query, $wpdb, $wp_version;
  
  $metaVars = array('custom1','custom2');
  $where .= ' AND (';
  foreach($metaVars as $metaValue=>$metaKey){
    if(!empty($_GET[$metaKey])){
      if($wp_version >= '2.3'){
        $clause .= " OR (m.meta_key = '".$metaKey."' AND m.meta_value LIKE '%".$wpdb->escape($_GET[$metaKey]) . "%') ";
      }else{
        $clause .= " OR (meta_key = '".$metaKey."' AND meta_value LIKE '%" . $wpdb->escape($_GET[$metaKey]) . "%') ";
      }
    }
  }
  $where .= substr($clause,3).') ';
  return $where;
}

Finally, here is the search_meta_groupby() function. I pulled this from the wordpress.org site and adapted it slightly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function search_meta_groupby( $groupby ){
  global $wpdb;
  
  // we need to group on post ID
  $mygroupby = "{$wpdb->posts}.ID";
  if( preg_match( "/$mygroupby/", $groupby )) {
    // grouping we need is already there
    return $groupby;
  }
  
  if( !strlen(trim($groupby))) {
    // groupby was empty, use ours
    return $mygroupby;
  }
  
  // wasn't empty, append ours
  return $groupby . ", " . $mygroupby;
}
All this is designed to get you started in creating custom field Wordpress searching. You might have to tweak the code involved here before you get it working.
Category: 

Share:

  • Add news feed
  • Bookmark this on Delicious

Add new comment