Enhancing WordPress Custom Fields with Search Filtering

Feb 15 2011 by Kirsty Burgoine | 43 Comments

Enhancing WordPress Custom Fields with Search Filtering

Custom fields are an excellent feature in WordPress. They allow you to store any extra information (meta-data) about a post that you may want.

When I first started using WordPress as a content management system, I shied away from them, as I thought they would be difficult to use for end-users (i.e. the client), but as I learned more about customizing the administration panels of WordPress, I began to realize what a powerful addition to a WordPress site they could be.

However, adding the ability to search your posts by custom field is a little tricky; the native search feature of WordPress doesn’t search custom field values.

In this guide, I’ll show you how to work with custom fields and how to make them even more powerful by adding the ability to display and filter them.

What we are going to do is create a very simple events listing page for a company that organizes Jelly co-working events, located in the UK. We will make the events listing page sortable by county. Each post will be an event with a title, description and a custom field for the area the event based in. (Alternatively, instead of using WordPress’s native Post post type, you can create a custom post type for events).

This guide assumes that you have ready-access to WordPress. If you would like to follow along step-by-step, you are encouraged to install WordPress on your computer instead of working with a live/production WordPress instance.

Setting Up the Custom Field in WordPress Admin

The first thing to do is set up the meta-data for each event. There is a strong argument to be made here for using the new custom post types feature that was introduced in WordPress 3.0, but to keep it simple, we will use the native Post post type in WordPress, and to indicate that they are events instead of regular posts, we will place them within a category called "Find a Jelly".

Start by adding each event as a post. Depending on your WordPress theme, you could also add custom thumbnails and a variety of additional information.

Once you have added the standard data and selected the correct category, scroll down to the Add New Custom Field section near the bottom of the Add New Post panel.

Click on Enter New, give your custom field a relevant name (Being in the UK, this example will use counties as the custom field key, although it could easily use states or regions). This will form the meta key in the database, so make sure its something simple (preferably one word) so that code-authoring isn’t cumbersome.

Next, add a custom field value for the counties custom field (the name of the county where the Jelly is located). In my case, the values could be Shropshire, Bedfordshire, Northamptonshire, and so on.

Click the Add Custom Field button to add the county meta-data, and then update your post.

From here on out, for each additional event you add, you will see the counties custom fields appear in the dropdown menu for custom fields; you don’t have to keep adding it in.

Once you have set up all of your events listings with their country custom field values, it’s time to start on the search filtering function.

Creating the Events Listing Page Template

Open page.php in your theme folder and save it as a new file. In this case, I’ve called the new page template as find-jelly.php.

Give the file a template name by adding this line to the top of the page:

Template Name: Find a Jelly

Now, when you create a new page for your directory, this page will appear in the list of available templates.

Creating the County Filtering Dropdown Menu

To create the web form that will allow users to filter the results, add this code to the find-jelly.php page template we created earlier, wherever you would like the dropdown input field to be displayed in the events listing page:

<form name="search" action="" method="get">
  <select name="county">
  <?php
  $metakey = 'county';
  $counties = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = %s ORDER BY meta_value ASC", $metakey) );
  if ($counties) {
    foreach ($counties as $county) {
      echo "<option value=\"" . $county . "\">" . $county . "</option>";
    }
  }
  ?>
  </select>
  <input type="submit" value="search" />
</form>

Let me explain what’s going on in the code block above.

The Markup

First of all, we have a basic HTML form with the action attribute left blank as we want the form to return to the same page when submitted. We set the method to get so that we can see the search criteria in the URL in the same way as the standard WordPress search. Using get is a nice touch that allows the user to share the search results link, as well as allowing us to use our analytics software (such as Google Analytics) to study popular event searches.

The <form> element contains a dropdown menu (<select>), with the <option> elements being the counties.

The submit button (<input type="submit">) allows for form submission; though, with a bit of JavaScript, you can submit the form when the user picks the option, saving them the user action of having to click on a submit button.

Populating the Dropdown Menu

The next part of our code is the tricky bit; we need to populate the <select> element with <option> elements of all the custom field values. To do so, we loop through all of the values in the database for the county custom field key; but we only want display unique values rather than every instance that they are attached to a post.

To do all of that, we use $wpdb->get_col(). $wpdb is a WordPress PHP class that allows us to construct our own SQL queries and do other database-related tasks. The get_col() method in $wpdb is used to select a specific column within our WordPress database.

First, we create a variable called string variable called $metakey that is assigned the name of our custom field (which is named county); this is optional, and just makes our code a little bit more readable.

Then using $wpdb->get_col(), we feed our SQL query as a prepared statement using WordPress’s handy $wpdb->prepare() method.

This is the SQL query from above (which has been rewritten and formatted slightly for discussion):

SELECT DISTINCT meta_value
FROM $wpdb->postmeta
WHERE meta_key = $metakey
ORDER BY meta_value ASC

This SQL query selects all unique records in the meta_value column of the WordPress postmeta, wherever meta_key is equal to "county"; it returns the results alphabetically.

Each result is then printed as the value attribute of each <option> element.

Once you have added the form, you should see something like the following image on your page; I have  styled this page, as well as added a Google Maps widget — we won’t cover that here.

Displaying the Search Results

OK, so that’s the actual search filter set up; now we need some results. To do this, we are going to add the following code to the find-jelly.php template after the code for the web form:

<?php
$counties = $_GET['county'];
if ($counties) {
  $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
  
  $args=array(
    'cat'=>19,
    'meta_value' => $counties,
    'paged'=>$paged,
  );
  
  query_posts($args);
} else {
  query_posts('cat=19&posts_per_page=4');
}

if ($counties) { ?>
  <h3>Your Search For <?php echo $counties; ?></h3>
  <?php } else { ?>
  <h3>Recently Added</h3>
  <?php }

if (have_posts()) :  while (have_posts()) : the_post();

$event_county = get_post_meta($post->ID, 'county', true); ?>
<div class="entry">
  <h2><a href=”</php the_permalink(); ?>” title=”<?php the_title_attribute(); ?>”>
  <?php the_title(); ?></a></h2>
  <?php the_excerpt(); ?>
  <?php echo $event_county; ?>
  <a href=”</php the_permalink(); ?>” title=”<?php the_title_attribute(); ?>”>  Read More</a>
</div>
<?php endwhile;  ?>
<?php else : ?>
<p>Sorry no results were found</p>
<?php endif; ?>

<?php wp_reset_query(); ?>

It looks like there is a lot going on there, simply because of the shear volume of code versus the first code block, but there isn’t, really; if you have worked with WordPress theme development before, the above will look pretty straightforward to you. Let’s break it down into its major components.

To start, we set up a variable to collect any form data that has been added to the page URL by looking into the $_GET[] array.

$counties = $_GET['county'];

Then we check to see if any data has been passed; if it has, we run a simple WordPress query:

if ($counties) {
  $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
  
  $args=array(
      'cat'=>19,
      'meta_value' => $counties,
      'paged'=>$paged,
  );
  
  query_posts($args);
}

The $paged variable is included so that the standard WordPress pagination can be used if there are a lot of results. I have included the 'cat' parameter (19 is the category ID of my category, but yours may differ) to make sure only posts from the Find a Jelly category are displayed; this isn’t necessary, but is an extra measure for fault-tolerance in case your client mistakenly adds the custom field to other posts outside of the Find a Jelly category. The meta_value needs to match our search query.

If the search function hasn’t been used, we need the page to display something, so I’ve set it to add the four most recent entries.

else {
  query_posts('cat=19&posts_per_page=4');
}

Next, we display a title depending on whether a search has been used:

if ($counties) { ?>
  <h3>Your Search For <?php echo $counties; ?></h3>
  <?php } else { ?>
  <h3>Recently Added</h3>
<?php }

And finally, we add the standard WordPress loop to loop through all of the results depending on the query used above. The only additional functionality is that I’ve added in the following:

$event_county = get_post_meta($post->ID, 'county', true); ?>

The above line of code gets the custom field information inside the loop and displays the county as part of each listing.

Save your file and upload it to your server, and you should now be able to sort all of your posts within the correct category by the custom field ‘county’.

For a live example of this, check out the Find a Jelly page on the UK Jelly website. You will see that I’ve taken the custom fields quite a lot further by integrating Google Maps with clickable markers listing all locations, as well as quite a lot of additional information about each Jelly.

Related Content

About the Author

Kirsty Burgoine is a designer/web developer specializing in WordPress. She runs her own Shropshire Web Design Company in the UK, is the owner of Imagine Shropshire (online magazine for news events in the county), and helps organize Shropgeek, A casual monthly meetup for like minded people. Follow her on Twitter as @kirstyburgoine, @Shropgeek or @ImagineShrops.

43 Comments

Jeff Geerling

February 15th, 2011

…or, using Drupal, you could create a View that has an exposed filter for the county, and displayed the results in a map view, and avoid writing the custom code/templates/queries. ;-)

I was wondering, though – with custom fields in WordPress, is there any Views-equivalent for WP? Would make doing custom searches, filtering, and displays of content many times easier than it is right now… and would tempt me to use WP again.

Vlad

February 15th, 2011

I actually thought of something similar to this a few days ago. Looks like you were faster!:) Thanks for the article!

Chris Quinn

February 15th, 2011

I have been looking all over for this. I want to be able to use custom fields so that potential clients can search my wordpress postings using custom key tags that I define. Plus this helps with search engine optimization because it allows for a wider search area on the blog. Thanks.

Dutch

February 15th, 2011

Nice post, because the default WP search function is crap. Bookmarked for future reference.

TheAL

February 15th, 2011

Awesome article. However, Jeff has a solid point about Drupal. Things like that are why I be lovin’ me some Drupal. But a lot of clients ask for WP, and WP has some sexy themes. So it’s nice to know how to do similar things in there.

Taimur Asghar

February 15th, 2011

Thanks for such useful hack/tutorial :)
Bookmarked, will implement in free time !

Jim

February 15th, 2011

Look into the Flutter plugin for wordpress. It allows you to create custom write panels that export as custom fields. That way your end user isn’t confused by the standard custom fields panel.

Snoggle News

February 15th, 2011

Wow these are some crazy afterthought effects! In fact, I haven’t even considered enhancing the custom post type variables within WordPress. It seems like such a no-brainer idea.. I’m glad to have stumbled onto the blog!

WPSPY

February 15th, 2011

Great info. Why don’t you release it as a plugin for dummies.

Brandon

February 15th, 2011

Wow, I actually have two jobs coming up that will need search functionality similar to this. Great post!

Devon

February 15th, 2011

Very straightforward and informative, is there a way to make this work with multiple custom fields?

Farid Hadi

February 16th, 2011

Great post. Well written and descriptive. Definitely bookmarked for future ref.
Thanks

Vasil

February 16th, 2011

Very nice feature and right on time. Thanks Kirsty for this.

Chris

February 16th, 2011

Maybe i’m missing the point?
But why don’t you just create a custom taxonomy “City”… then you would get the same functionality with built-in wp functions. You could easily relate your events (post-type) to a city (category or tag). WordPress would do the rest of the job, dropbox with cities, search results with category pages, …
Or do i needd another coffee?

Best
/Chris

Jacob Gube

February 16th, 2011

@Chris: That is a good option (custom taxonomies). I think though this is just more of a general proof-of-concept of the things you can do with custom fields. It gets you thinking of what else you can do with custom fields, which I feel a lot of devs shy away from because of the very fact that Kristy mentions in the intro: it seems too complex for end-users. But when (again, paraphrasing from what Kristy said in the intro), you combine it with customizing the admin panels, it can be powerful and convenient for enriching posts with meta-data.

What she did can be approached several ways; you can even just create normal categories (and not use a custom taxonomy) for each country. But the point isn’t to show you how to create a search filter in WordPress (which is way too specific of a topic), but rather, to show what you can do with custom fields. Otherwise, we would’ve called this post “How to create a country search filter for events listings in WordPress”

Chris

February 16th, 2011

@Jacob thanks, clear now.

Kirsty Burgoine

February 16th, 2011

Thanks everyone for your AWESOME Comments!

Drupal is definitely an option for something like this but as many people only use WordPress I wanted to show how easy it is to extend the standard functionality and do more with WordPress specifically.

There are a number of plugins out there that can help manage Custom fields, including Flutter and PODS, I’ve used several of them myself to see what they can do, but as a PHP developer I like to get my hands dirty and customise the admin myself.

With the many systems and plugins available to do something like this available, I could have approached this from any number of angles, taxonomies is a good option but when I thought about writing this tutorial I was actually building something with more custom fields than just the county so it made sense to keep all of the data as the same type.

:)

Rob Muzo

February 16th, 2011

Nice code though you have a bug:

<a href=”” title=””> Read More

should be

<a href=”” title=””> Read More

Rob Muzo

February 16th, 2011

that didn’t post properly:

Line 31
<a href="”

PHP tag is wrong

Ivan Storck

February 16th, 2011

How would you implement a search for partial terms? For example if you had a set of topics (Sustainable Development, Sustainable Building, Basket Weaving) and wanted all topics with “Sustainable*” returned?

NickyS

February 17th, 2011

This would be even better in used in a custom post type, really nice tutorial

Kirsty Burgoine

February 17th, 2011

Hi Ivan,

A couple of ways you could do that, probably the easiest would be if the search terms are definitely not going to change you could use the php explode() function to break up the term searched for and create an array. Something along the lines of:

$search_term = $_GET['search_term'];
$partial = explode(” “, $search_term);

Then amend your query_posts so that meta_value => $partial[0];

If you think your terms would change regularly you would probably have to use $wpdb and create a custom select query that used LIKE to find all results that are similar and not exact matches.

Hope that helps :)

abelbrain

February 17th, 2011

very useful tutorials…

Nicolas

February 23rd, 2011

You can add ‘meta_key’=>’county’ to your args to be sure the meta_value matches only the ‘county’ meta_value.

David

March 11th, 2011

Well done. I will bookmark it for a future. But personaly because my blog is a gallery i use ajax search.

Cricket La Chica

March 24th, 2011

How would you do searching for more than 1 custom field though? Like say, aside from County, you also have a City custom field, and want to filter through that?

kareem

April 20th, 2011

thanks a lot for this valuable article.
But how about doing a search on multiple custom fields ? something like “WHERE SIZE = so.. AND COLOR = ..”.
Thanks for any thoughts about this.

SGC

May 31st, 2011

Your tutorial was a perfect example to get me moving forward. Thank you.
I have used a similar extension to standard post with custom fields and found that as the customer wanted vistors to enter records, an entry page using TDOmini forms (great plugin) was the simplest and cleanest for that situation. Really like this tutorial for filtering now I just need to modify it for 3 custom fields. Cost (less than or equal to), Time (less than or equal to) and Goal (equal to and maybe multi select later).

mikou

July 11th, 2011

Yes, an example with multiple custom keys and values would be great for those with little php knowledge;
thanks a lot for that anyway!

mikou

July 11th, 2011

Is the ‘cat’ in the array referring to a page parent id we want as a cat?
If not what does it refer to as you seem to be referring to pages, which from what I have understood, don’t have categories associated in wordpress (a part from parent pages)?

Thanks

mikou

July 11th, 2011

just ignore my last message as understand you are actually referring to posts within a page template. cheers

ArleyM

July 18th, 2011

Thank you so much!!!

Maxime

July 20th, 2011

Very useful indeed! You saved me!
I’m putting this filter at the top of each category.
How can I populate the Drop Down menu only with the custom field’s posts of that specific category I’m currently in (instead of retrieving custom field’s all posts).
Thank you again for this helpful article!

Monica

July 22nd, 2011

This is great. Thank you! Do you know any reason why it would not work when my custom field is in a custom post type though? It only displays the results when I test with custom field in a normal post? Also I am working on code to merge with multiple custom fields (state = OH and type = ‘public’ to show all public areas in Ohio). Did anyone who asked about multi fields come up with the right syntax for the query to share?

Demon Lee

August 2nd, 2011

I would be very interested in a multiple selection category, I am working on a project for car sales and to be able for the user to select a few preferences before searching would make life so much easier.

Peann

August 4th, 2011

I have managed to get taxonomy and custom fields to appear in a post. I’m creating a directory with towns and counties in it too and I have my list of counties What I cannot workout from your tutorial is how I would make another page where members of the public could search for someone in a particular town and county or under a particular category of membership.

Aguito

August 12th, 2011

Thank you so much! This is very useful!

Yasser

October 1st, 2011

Awesome Tutorial! I tihnk this will be really useful to me in future projects… thanks you ;)

Titus

October 9th, 2011

Is there a wordpress solution already available that allows users to upload videos and attach a ‘city’ to them so when people search the website, the results can be sorted by city?

will

October 28th, 2011

how can i adjust that sql query to only include custom meta value that is being used. For instance if it is in a post not published?

Fernando

November 2nd, 2011

It works fine, so… how can I include two meta_data for search? I just need this tip to create my own theme,please help!

Greg

November 17th, 2011

This example shows just one custom field (counties), correct? Can this tutorial be expanded to show multiple custom fields? Essentially choose this AND that then submit?

Paul

November 26th, 2011

you shouldn’t be using query_posts.
Here is a better method that uses the pre_get_posts filter:
http://www.billerickson.net/customize-the-wordpress-query/
since WordPress 3.1 you can use the meta_query parameter to search by custom field values.
http://codex.wordpress.org/Class_Reference/WP_Query

Leave a Comment

Subscribe to the comments on this article.

Mobify empowers marketers and developers to create amazing mobile web experiences. Tap to learn more

Mobify