
I like having an easy-to-use search bar that isn't redundant and doesn't require several different search bars to do things that a single search bar should be able to do. PhpBB, I'm looking at you.
Today I'll teach you how to add some options to your WordPress search bar to search for several different things. The search bar will allow the user to search:
- All post types and categories
- Only blog post types
- Only portfolio post types (which in this example will be an array of three different kinds of post types in itself)
- Only in the tutorial category
Set up your search bar as you normally would in your template. For this example, I'm just going to have a search bar on an empty page, for simplicity's sake.
Modifying your template
Open up the template that has your search bar in it. Your search form should look something like this:
<form id="search" name="searchform" method="get" action="<?php bloginfo("url"); ?>"> <section id="searchMain"> <input type="search" id="s" name="s" title="Search Blog" placeholder="Search My Website" /> <button type="submit" value="search" id="searchsubmit">Search</button> </section> </form>

Here I've used a HTML5 element called section to wrap around my form elements. You can use a div if you're not comfortable using HTML5 elements. We need a container element for these elements because the options are going to be in a separate container, but still in side the form.
Create another section element underneath the searchMain section, and call it something like searchOptions. Populate this element with some radio buttons and some labels, as you would if you were setting up any old regular form with a radio selection. The "name" for these radio buttons will be "post_type". Set up the values to represent what you would like the post_type to be when the user searches. My code at this point is now looking like this:
<form id="search" name="searchform" method="get" action="<?php bloginfo("url"); ?>"> <section id="searchMain"> <input type="search" id="s" name="s" title="Search Blog" placeholder="Search My Website" /> <button type="submit" value="search" id="searchsubmit">Search</button> </section> <section id="searchOptions"> <input type="radio" value="all" name="post_type" id="searchOptionsAll" checked /> <label for="searchOptionsAll">Search All</label><br /> <input type="radio" value="post" name="post_type" id="searchOptionsBlog" /> <label for="searchOptionsBlog">Search Blog Only</label><br /> <input type="radio" value="portfolio" name="post_type" id="searchOptionsPortfolio" /> <label for="searchOptionsPortfolio">Search Portfolio Only</label><br /> <input type="radio" value="tutorials" name="post_type" id="searchOptionsTutorials" /> <label for="searchOptionsTutorials">Search Tutorials Only</label> </section> </form>

Note: I've added the "checked" attribute to the first radio button. This will act as the default action. This way you don't need to worry about coding in a fallback in case someone doesn't select an option.
If you would like a different option to be used as the default search, remove the checked attribute from the first radio button and add it to the one you want to be the default.
So now we've got a pretty good looking form coming together.
Functions.php
You've got a pretty swanky form going now, but does it actually do anything? If you click search, you'll notice it sends ?s=%searchterm%&post_type=%yourselection% to the search results page up in the URL. We're now going to take advantage of those GET variables and do some pretty cool things with them.
Open up your functions.php and at the bottom, paste in the following code:
/*********************************** * * SEARCH FILTER * http://speckyboy.com/2010/09/19/10-useful-wordpress-search-code-snippets/ * ***********************************/ function SearchFilter($query) { if ($query->is_search or $query->is_feed) { // Portfolio if($_GET['post_type'] == "portfolio") { $query->set('post_type', array('artwork', 'websites', 'motion')); } // Tutorials elseif($_GET['post_type'] == "tutorials") { $query->set('category_name','tutorials'); } // EVERYTHING! MWAHAHAHAHAHA elseif($_GET['post_type'] == "all") { $query->set('post_type', array('artwork', 'websites', 'motion', 'post')); } } return $query; } // This filter will jump into the loop and arrange our results before they're returned add_filter('pre_get_posts','SearchFilter');
I like to always attribute links to the places I find the snippets of code I use, so you'll notice I've included a link to the site where I originally found the snippet we'll be using today.
I've added two checks, the first one checks if the page we're on is a search, the second one checks if we're looking a feed. The feed part is optional and you can remove it. I included it because I also wanted to have these queries available as custom feeds.
Once the feed or search check is confirmed, it will move on to look at the $_GET values for the "post_type" variable:
- If it finds "portfolio" it will create a custom query to return all posts in the "artwork", "websites" and "motion" post types that match the search terms. These are proper custom post types I had previously set up in the back-end using the Custom Post Type UI plugin.
- If it finds "tutorials" it will create a custom query to return all posts in the tutorials category that match the search terms.
- if it finds "all" it will create a custom query similar to the first one, however instead of just returning those three post types, it also returns "post" post types, which are the default blog post types for WordPress. This way you're essentially searching all four post types for the same term.
Notice I didn't need to set up a custom query for the "Search blog only" option. If you look back at the code for the radio buttons, the value it sends is simply "post". As we've learned in the code snippet above, "post" is the post type for the default WordPress blog posts. The variable the search form sends to the search results page is post_type, which is actually a real variable you can pass to WordPress at any time. As such when you search only the blog it will send ?post_type=post to the search results page and WordPress will know exactly what to do with this out of the box.
Now you'll probably want to change the post_types above to use the post_types you want to search for on your own WordPress install. Unless you find yourself in the incredibly coincidental scenario of having exactly the same sort of post types as me. In which case, high five!
So now your search form should be fully functional and ready to go!
Some jQuery magic
If you're like me, you like a search bar to not take up too much room, and be fairly easy to access. These new options seem to take up a lot of space and don't look very good. What can we do about that? Well, how about we add a show/hide options button? Sounds pretty good to me!
Go back to your search form template and add in a link just after the search button. Make sure to give it a unique ID so we can target it in jQuery later. Here I've called mine searchAnchor:
<section id="searchMain"> <input type="search" id="s" name="s" title="Search Blog" placeholder="Search My Website" /> <button type="submit" value="search" id="searchsubmit">Search</button> <a href="#" id="searchAnchor">Search Options</a> </section>

Okay, great. Now we have a little link there. If you already have a scripts file with other jQuery business in it, open that up. If not, create a scripts.js file and dump it in to your theme folder. Enter in the following code:
$(function() { $("#searchAnchor").click(function(){ $("#searchOptions").toggle(); }); });
Make sure you link up your new scripts.js file to your theme, then try it out! Now when you click the link it hides the options. Clicking it again shows them again! Woo! But we'll probably want it hidden by default. So open up your CSS file and add the following:
#searchOptions {display: none;}
Lookin' good, good lookin'. Now it's hidden by default, and clicking on the "search options" link shows them. Now all that's left is to style that puppy up. Add some background colours, borders and all sorts of crazy CSS3 goodness and you'll soon end up with a pretty swanky lookin' form.

If I'm still using the db2011 theme while you're reading this then there should be a live, working demo right there in the top right corner of this very website!
Great tutorial David. I just may have a use for this on an upcoming project! Cheers!
(Haha. I had to go all the way to your twitter account to find out what your first name was!)
Thanks Chad!
Maybe I should rectify that, my name is now on the about page.
I love this solution!! I just have one issue I cannot solve. I cannot get ALL to display all posts. It keeps returning only the custom post type. I only need 2 options to filter.
Here is my modified functions
/***********************************
* SEARCH FILTER
* http://speckyboy.com/2010/09/19/10-useful-wordpress-search-code-snippets/
***********************************/
function SearchFilter($query) {
if ($query->is_search or $query->is_feed) {
// STAFF
if($_GET['post_type'] == "swc_staff") {
$query->set('post_type','swc_staff');
}
// EVERYTHING!
elseif($_GET['post_type'] == "all") {
$query->set('post_type', array('swc_staff', 'post'));
}
}
return $query;
}
// This filter will jump into the loop and arrange our results before they're returned
add_filter('pre_get_posts','SearchFilter');
my fields
Search All
Search Staff Only
Thanks Stu!
The code looks good, I wonder why it isn't working properly. Can you try entering in a search URL manually and see if that displays the correct post types?
Something like: /?s=a&post_type=all
Hmm that URL works
http://www.swclinics.com/website/?s=a&post_type=all
Now the problem must be in my options.
These are my two field options. They look right?
My "all" radio selection only returns staff members and now one post. No pages or other posts. Hmm so strange. If you search for "a" you get all staff instead of one other post in other words.
I figured it out. You need to add 'page' in addition to 'posts' to the array for "all".
Awesome! Glad you figured it out
Hello David, I'm a web developer in Vietnam. I read your article and feel great. But I would like paginate list the post_type. Thanks a lot !
The pagination seems to be working correctly on my website. I don't remember doing anything specifically to make it work but I have my template up on Github if you feel like looking through the code and seeing if anything jumps out at you: https://github.com/dbaines/dbaines2012-Wordpress-Theme
Sorry I couldn't be much more help.
my fields
Search All
Search Staff Only
SO in other words a solution for two options. ALL and one custom post-type.
Very useful! Thanks for posting
Amazing tutorial!
Do you know how to make the search also work with custom fields?
So lets say my posts contain a "location" custom field. A user can type in a location and the results will be displayed.
Any thoughts?
Sorry Anthony I haven't really had much experience with custom fields.
This thread on the WordPress forum might help.
You could combine it with the code in my post so that the user clicks on "search locations" and it passes a ?type=locations variable or something to the results page. Then on your results page you could use a check for "locations" variable and then change the query_posts as suggested in the forum post.
Hope that helps or at least gives you an idea
Love this! Thanks a lot.
Well, this is what I was looking for. Nice tutorial about post_types. A few tweaks and it's perfect!!!
If You want to have an option to search in certain category, get category id from Editiong category URL (Tag_ID). Then to browse ALL (everywhere), you need to type any, my working example:
// Naujienos
if($_GET['post_type'] == "category1") {
$query->set('cat','5');
}
elseif($_GET['post_type'] == "category2") {
$query->set('cat','6');
}
elseif($_GET['post_type'] == "all") {
$query->set('post_type', "any");
}
and change accordingly radio buttons values in your form. Insert value's category1 and category2. All stands for search everywhere
Hi admin, i've just add below code into functions.php:
function SearchFilter($query) {if ($query->is_search or $query->is_feed) {
// Get Posts
if($_GET['post_type'] == "post") {
$query->set('post_type', array('post'));
}
// Get Products
elseif($_GET['post_type'] == "product") {
$query->set('post_type', array('product'));
}
// EVERYTHING!
elseif($_GET['post_type'] == "all") {
$query->set('post_type', array('post', 'product'));
}
}
return $query;
}
add_filter('pre_get_posts','SearchFilter');
Now, i only want search from post title with post_tyle = post. Give me code. Thanks so much !
Here is a function that will return only titles in your searches.
Nice post, thanks for sharing. How could I make one of the options to search tags?