Employee Post

Hacking WordPress Search for Fun and Profit!

I spoke at WordCamp SLC last month on the topic of WordPress search. Why did I speak on the topic of WordPress search? you might ask. I mean, everybody knows WordPress search is dumb and doesn’t work very well, you might add.

I’m glad you asked that question!

My talk (slides avaialable) was based on the pretext that there are three common misconceptions of WordPress search by users and developers alike:

  1. “I don’t know anything about WordPress search”
  2. “WordPress search is hard”
  3. “WordPress search sucks”

I’m here to tell you that you are wrong on all counts.

I don’t know anything about WordPress search

Let’s start with the first and probably the easiest item — that for some reason you don’t know anything about search. I know for a fact that if you’ve been using and/or developing for WordPress for any amount of time, this is absolutely untrue. You know this:

?s=your search query

You should know by now that if you enter in your domain followed by a slash and that snippet above that you will perform a search on your site for that particular query. (Didn’t know you could do that? Try it right now. There, now you do.) You should understand implicitly, based on how it works, that when you put that in your URL, WordPress will then do a database query based on your search phrase and show you what comes up. That right there is the foundation of everything you need to know about WordPress search. If you know that, everything else I’m going to talk about related to queries and searching the database should make sense because it all comes back to that string up there and how it works.

WordPress search is hard

Next there’s this idea that search is hard for some reason. I became the “expert” on search by default mostly because no one else wanted to work on it. Even among developers, there’s this idea that search is some black hole that you don’t want to go into otherwise you get sucked into hours and hours of extra work and research. Let me tell you something: it isn’t.

If you are even just getting started with WordPress development, you should be familiar with the concept of the WordPress Loop, the if ( have_posts() ) : while ( have_posts() ) : the_post(); magic that makes your content show up on the page and, most importantly, makes the right content show up on the page. So, let’s take a step back and look at what WordPress is actually doing when it runs the Loop.

Recognize this? ?p=123

You should. That’s the default URL to a post when the default permalink settings are set. It’s probably the first thing you change when you set up your WordPress site unless for some bizarre reason your server does not support “pretty” permalinks. You may also have already discovered that there’s a correlation between the numeric value in that string (the 123 part) and the specific post it refers to — namely, that number is the post ID. We can conclude, then, that when I enter ?p=123 after my domain’s URL, that I should pull up a post with the ID of 123, assuming it exists. Even when “pretty” permalinks are turned on and this string — referred to as a query string — is hidden, it’s still there working its magic. And this is important because this is how WordPress knows what post you’re trying to display. When you go to a post’s URL, WordPress looks at the query string and uses that to determine what content it should be displaying — in this case, it looks at the post ID, does a little database query, and pulls up the matching post content.

WordPress does the same thing with every other type of page and content. Category archives for the “fluffy bunnies” category will use the query string ?cat=fluffy-bunnies and post type archive pages for the “songs” post type might use ?post_type=song.

What does this have to do with search? you might be thinking. Everything. Because search works is (almost) exactly the same way.

Each one of the keys in those query strings (the ?cat, ?p, and ?post_type part) corresponds to a WP_Query argument, and the value (everything after the =) is what we’re actually querying for. The most you really need to know about this is that it exists and it’s part of what WordPress already does in the Loop.

?s is just another one of these possible arguments that can be passed to WP_Query.

wait-what

The way it works, though, is a little different than the others (though not that much different than, say, ?cat=fluffy-bunnies or ?post_type=song). Instead of looking for something specific (like a post ID), or relational (like a category or post type), WordPress does a database query that looks something like this:

( $wpdb->posts.post_title LIKE %s ) OR
( $wpdb->posts.post_content LIKE %s )

All that is doing is searching the database for post titles and post content matching your query. WordPress only searches post titles and post content. It does not do anything other than searching post titles and post content. And this is (part of) why some people might criticize WordPress’ default search as being “dumb”. Personally, I think this is a matter of expectations — we’re so used to Google and predictive searches that when confronted with something that doesn’t predict the thing that we need before we explicitly say we need it, it feels like a letdown.

Now that you know how search works, let me take a moment to blow your mind:

You can add all these query arguments to search.

tim-and-eric-mind-blown

The way this works is through query strings that look like this:

?s=my%20search%20query&cat=fluffy-bunnies&post_type=song

The string above will search all posts in the “fluffy bunnies” category that are “song” posts with the search phrase “my search query” in the post title or the content. WordPress does all the normal WordPress Loop things with the added bonus that it also performs a query on post titles and content.

WordPress search isn’t hard and you probably already know all this stuff. (You just may not know you know it.)

That brings us to the final argument against WordPress search:

WordPress search sucks

As you can see from what I think is an incredibly useful query that does a term search within a multi-criteria archive search, search can be incredibly powerful. It doesn’t suck, it does exactly what you ask it to. So let’s take a look at how to ask it to do some more intelligent things.

Here’s that search query again: ?s=my%20search%20query&cat=fluffy-bunnies&post_type=song

If this looks familiar, it should. This is just like the arguments that you might pass to WP_Query. In fact, you could rewrite this as a WP_Query like this:

$wds_query = new WP_Query( 's=my%20search%20query&cat=fluffy-bunnies&post_type=song' );

if ( $wds_query->have_posts() ) : while ( $wds_query->have_posts() ) : $wds_query->the_post();

This could be rewritten a little bit cleaner like this:

$args = array(
     's'         => 'my%20search%20query',
     'cat'       => 'fluffy-bunnies',
     'post_type' => 'song'
);

$wds_query = new WP_Query( $args );

if ( $wds_query->have_posts() ) : while ( $wds_query->have_posts() ) : $wds_query->the_post();

This is the same stuff you already do when you create other types of custom loops.

Great. But how do I use this?

I’ll give you one really simple example and then link you to two, more complex examples that I used in my presentation at WordCamp SLC. Let’s say you want to create a search form that searches within the “article” post type within the “music” taxonomy for posts tagged with the “jazz” term. Your search form could look like this:

<form role="search" method="get" class="search-form" action="<?php get_home_url( '/' ); ?>">
     <label>
          <input type="search" class="search-field" placeholder="Search articles about jazz" value="" name="s" title="Search for:" />
     </label>
     <input type="hidden" name="music" value="jazz" />
     <input type="hidden" name="post_type" value="article" />
</form>

A few examples of more complex search queries can be seen in my presentation slides and the code here and here.

Rather than “sucking”, WordPress search can be incredibly powerful and customized right out of the box without any need for external plugins to make search “work better”. With the form example above, you can imagine a search form that has a dropdown for the user to specify the type of search, a simple select input to choose from a list of post types, taxonomy terms, post statuses, anything you can run a WP_Query on. Now, if you need to actually index the content of your post for relationships or to rank posts by relevance, a search plugin like SearchWP might be up your alley. But historically, these plugins are very large, create huge amounts of entries in the database (out of necessity) and are often not really needed. You can, instead, just build on the core search functionality and just expand it to meet the needs of the site you are working on.

Comments

3 thoughts on “Hacking WordPress Search for Fun and Profit!

Have a comment?

Your email address will not be published. Required fields are marked *

accessibilityadminaggregationanchorarrow-rightattach-iconbackupsblogbookmarksbuddypresscachingcalendarcaret-downcartunifiedcouponcrediblecredit-cardcustommigrationdesigndevecomfriendsgallerygoodgroupsgrowthhostingideasinternationalizationiphoneloyaltymailmaphealthmessagingArtboard 1migrationsmultiple-sourcesmultisitenewsnotificationsperformancephonepluginprofilesresearcharrowscalablescrapingsecuresecureseosharearrowarrowsourcestreamsupporttwitchunifiedupdatesvaultwebsitewordpress