Enable Custom Field Searching With Wordpress 2.6
Published by philipnorton42 on Fri, 09/05/2008 - 13:52I 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; } |
Add new comment