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.
Write a comment