DEV Community

Cover image for WordPress Filter Search Results By Category and Tag
nightwolfdev
nightwolfdev

Posted on • Updated on • Originally published at nightwolf.dev

WordPress Filter Search Results By Category and Tag

Many WordPress themes provide a simple search form that includes a single input field for entering your search term. The search results are helpful, but what if you wanted to provide visitors with a way to filter those results by category and/or tag and change the order? Let’s learn how!

Standard Search Form

The action property on a form defines the url that should load when the form is submitted.

<form method="get" action="/">
Enter fullscreen mode Exit fullscreen mode

Every field in a form should have a name property that becomes a url parameter. A standard WordPress form includes a single input field using a name value of s, which represents the search term.

<input type="search" name="s">
Enter fullscreen mode Exit fullscreen mode

Let’s say you search for the word table. You’ll see the url changes to something like:

https://nightwolf.dev/?s=table
Enter fullscreen mode Exit fullscreen mode

WordPress has other url parameters that can help us achieve our goal of filtering search results.

Query Vars

WordPress has both public and private query vars. Public query vars can be used as url parameters. Private query vars can only be used in PHP when building a query using functions like WP_Query.

Filtering by category and/or tag as well as changing the order can all be done using the public query vars called category_name, tag, orderby, and order! We just have to build them into the resulting search url.

Search Template

When a visitor performs a search, the template used to display the search results is called search.php. Let’s edit that search template to include a form with fields for filtering results.

get_query_var

We need to check if there are url parameters present and grab their values. We can use the get_query_var function.

To see if the visitor filtered the search results by category, check the category_name query var and save its result in a variable called $filterByCategory.

$filterByCategory = get_query_var( 'category_name' );
Enter fullscreen mode Exit fullscreen mode

To see if the visitor filtered the search results by tag, check the tag query var and save its result in a variable called $filterByTag.

$filterByTag = get_query_var( 'tag' );
Enter fullscreen mode Exit fullscreen mode

To see if the visitor filtered the search results by changing the order type, check the orderby query var and save its result in a variable called $orderBy.

$orderBy = get_query_var( 'orderby' );
Enter fullscreen mode Exit fullscreen mode

To see if the visitor filtered the search results by changing the order, check the order query var and save its result in a variable called $order.

$order = get_query_var( 'order' );
Enter fullscreen mode Exit fullscreen mode

Search Term

Let’s create an input element, which will include the current search term using the_search_query function.

<input type="search" name="s" value="<?php the_search_query(); ?>">
Enter fullscreen mode Exit fullscreen mode

Filter By Category

Let’s create a select element, which will list all of our categories. Define the name property with the query var called category_name. When the form is submitted, it will include the category_name query var into the url, filtering the results by the selected category.

<select name="category_name">
Enter fullscreen mode Exit fullscreen mode

To get a list of categories, we can use the get_categories function. We don’t want the Uncategorized category to appear as an option so make sure to exclude that by passing arguments to the get_categories function.

$args = array(
  'exclude' => '1'
);

$categories = get_categories( $args );
Enter fullscreen mode Exit fullscreen mode

Let’s loop through each category and output an option element. If the current category we’re looping through equals the filterByCategory, we’ll include the selected attribute so it appears as the selected option. The option value will be the category slug and the option text will be the category name.

foreach ( $categories as $category ) {
  $selected = $category->slug === $filterByCategory ? 'selected' : '';

  echo '<option value="' . $category->slug . '" ' . $selected . '>' . $category->name . '</option>';
}
Enter fullscreen mode Exit fullscreen mode

Filter By Tag

Let’s create a select element, which will list all of our tags. Define the name property with the query var called tag. When the form is submitted, it will include the tag query var into the url, filtering the results by the selected tag.

<select name="tag">
Enter fullscreen mode Exit fullscreen mode

To get a list of tags, we can use the get_tags function.

$tags = get_tags();
Enter fullscreen mode Exit fullscreen mode

Let’s loop through each tag and output an option element. If the current tag we’re looping through equals the filterByTag, we’ll include the selected attribute so it appears as the selected option. The option value will be the tag slug and the option text will be the tag name.

foreach ( $tags as $tag ) {
  $selected = $tag->slug === $filterByTag ? 'selected' : '';

  echo '<option value="' . $tag->slug . '" ' . $selected . '>' . $tag->name . '</option>';
}
Enter fullscreen mode Exit fullscreen mode

Order By

Let’s create a select element with options to order by Date or Title. Define the name property with the query var called orderby. When the form is submitted, it will include the orderby query var into the url, changing the type of order.

<select name="orderby">
Enter fullscreen mode Exit fullscreen mode

Create an array of order by options.

$orderByOptions = array( 'date' => 'Date', 'title' => 'Title' );
Enter fullscreen mode Exit fullscreen mode

Let’s loop through each order by option and output an option element. If we have no orderBy value and the current option we’re looping through equals date, or the current option we’re looping through equals the orderByValue, we’ll include the selected attribute so it appears as the selected option. The option value will be the orderByValue and the option text will be the orderByText.

foreach ( $orderByOptions as $orderByValue => $orderByText ) {
  $selected = (!$orderBy &amp;&amp; $orderByValue === 'date') || $orderByValue === $orderBy ? 'selected' : '';

  echo '<option value="' . $orderByValue . '" ' . $selected . '>' . $orderByText . '</option>'; 
Enter fullscreen mode Exit fullscreen mode

Order

Let’s create a select element with options to order by ASC or DESC. Define the name property with the query var called order. When the form is submitted, it will include the order query var into the url, changing the type of order.

<select name="order">
Enter fullscreen mode Exit fullscreen mode

Create an array of order options.

$orderOptions = array( 'DESC', 'ASC' );
Enter fullscreen mode Exit fullscreen mode

Let’s loop through each order option and output an option element. If we have no order value and the current option we’re looping through equals DESC, or the current option we’re looping through equals the orderOption, we’ll include the selected attribute so it appears as the selected option. Both the option value and option text will be the orderOption.

foreach ( $orderOptions as $orderOption ) {
  $selected = (!$order &amp;&amp; $orderOption === 'DESC') || $orderOption === $order ? 'selected' : '';

  echo '<option value="' . $orderOption . '" ' . $selected . '>' . $orderOption . '</option>';
Enter fullscreen mode Exit fullscreen mode

Filtered Search Results

With all that in place, when the form is submitted, it will include the query vars into the url and update the search results based on your selections!

https://nightwolf.dev/?s=table&amp;category_name=articles&amp;tag=javascript&amp;orderby=date&amp;order=DESC
Enter fullscreen mode Exit fullscreen mode

Visit our website at https://nightwolf.dev and follow us on Facebook and Twitter!


Top comments (0)