How to Add Post Filters to Your WordPress Site

A frequent request I come across is the ability to let users filter, or sort, posts on the front-end of their website.

Perhaps users want to view posts alphabetically, or maybe see only those posts with thumbnails? This already makes sense for regular posts but can be even more meaningful in the case of products, photos or other content types.

In today’s Weekend WordPress Project I’ll give you a quick rundown of how you can implement a feature like this in the Twenty Fifteen theme. Let’s get cracking!

Creating A Child Theme

As always, you need a child theme. We have a guide to child themes right here on WPMU DEV, I recommend giving that a read if you are not familiar with child themes.

Creating Controls

Let’s add three controls: one for ordering the posts, one for setting the direction of sorting and one for showing only posts with thumbnails.

The first step is to copy the parent theme’s index.php into our child theme.

Open the index.php file in your child theme and paste the following HTML below the main container (which should be on line 20):

And here’s what it looks like on the front-end:

Forms
Not so pretty yet but our form is in the right place

As you can see we are lacking a bit of styling. Let’s resolve that by adding some styles to the stylesheet:

Styled Filter
More work could be done but it looks much nicer

A reaction I frequently hear from newcomers to programming is: “how did he know that these are the styles that will make it blend into the theme?”

The solution is pretty simple: I cheat. I use the developer tools in Chrome to inspect the regular article elements. In this case, it let me see how the elements get their box shadow and their margins and I simply applied these rules to my own element.

Modifying the Query

Let’s select “order by title,” “ascending” and “posts with thumbnails” and submit the form. You should actually see a change without doing anything to the code.

To see why, let’s inspect the URL. It should be something like this:

http://yourdomain.com/?orderby=post_title&order=DESC&thumbnail=only_thumbnailed

The tidbits of information can be recalled in our PHP scripts using the $_GET variable. WordPress already knows what the order and orderby parameters mean and it uses them in the default query. As a result, if we only need ordering and order direction we’re actually all done.

That’s all great, but again, how did I know this? I could have used “order_by” as a parameter instead of “orderby.” In this case WordPress does not pick up on our intentions. I had a look at the WP_Query documentation in the WordPress Codex where there are a bunch of parameters, many of which can be used in URLs.

Now, let’s implement our post thumbnail parameter. A post has a thumbnail if it has metadata with the key _thumbnail_id associated with it. We’ll need to modify our query to make sure this is taken into account. Let’s do this now with query_posts().

Paste the following code above the get_header() function at the top of the file:

We merge the parameters of the original query with our own new parameter, which results in a different set of posts. Our form now works but it doesn’t remember our selections. Let’s fix that by rewriting our form and using some PHP.

Smarter Forms

In addition to listing all the options of the order by selector we need a way to indicate which one is selected. If we were to do this without a loop it would look something like this:

Do you understand any of that? I don’t blame you! Within each options we’re checking if the currently selected value is equal to the value of the option. If it is, we output the selected property. Let’s make this a lot cleaner with a loop:

This is a bit longer but only because we have three options. This is a way better format for managing any kind of selection. Let’s extend this to the whole form:

All done. The form should now remember our selections based on the $_GET variables in the URL.

WordPress Behavior

Remember how I mentioned that I know to use “order” and “orderby” because I looked at the WP_Query documentation? This is good practice, but it may lead to unexpected results. Find the slug of a category you have, say this category is “wordpress.”

Now use the following URL: http://yourwebsite.com/?category_name=wordpress. You should see your category archive, listing all your WordPress posts. This is just fine, but we have two problems:

If you have pretty permalinks turned on (which you should), the page has been redirected to a new URL, most probably http://yourwebsite.com/category/wordpress. Our filters will not be visible because the archive.php file handles this view, not index.php. In addition, our category name is not passed as a URL parameter so we will need to use some additional trickery to make our filters work.

The shortcut way of making this work is to deliberately not use the same parameters WordPress uses. You could pass the category name using the catname parameter in the URL since WordPress will not pick up on this. You can then feed this to the query using the correct parameter name. Something like this:

The alternative would be to use a function instead of outputting our form in index.php as is. You would need to detect the category from the WordPress query itself and display the current selection based on that.

Conclusion

Adding your own filters is not all that difficult but requires a bit of fiddling. In our case you may want to make sure the pagination is removed when the order is set to random. It could be replaced by a “show more randomness” button, which simply reloads the page.

Hopefully this article has given you the basics of how you can accomplish this for yourself and you will be able to build the filters you need.

If you have any questions about this project, feel free to ask in the comments.