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.

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.

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.

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.

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.

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
12 + 4 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.