In doing a complete redesign and rebuild of a fairly busy website (and taking it from a custom PHP backend to WordPress), my research on how the site was being used informed me that my biggest goal was maintaining a dead-simple search function. In addition to it just working well, I also had the precedence of a well-written search results page which ranked everything by an ever-changing Relevance vs. Time calculation. Now, one of the most common complaints/tutorial topics about WordPress involve improving search via extra code, plug-ins, or a better results page. Since the combination of reading endless pages and trying numerous plug-ins helped me get to the right place, so I hope this post aids you in your ‘search’.

Now, as with many folks using WordPress more as a CMS, I’m using categories to build function into various parts of the site. This being the case, along with many other circumstantial factors, there’s many opportunities for pages, posts, and events (which are posts belonging to certain categories) to be named the same. In my example, we’ll use the get_post_type function to state clearly if the search result is a page or a post, and then an extra condition to make a third ‘type’, which is really a collection of categories. I’ve also got some other WP functions thrown in.

In search.php (Search Results), find
while (have_posts()) : the_post();

Below that, we determine if the result is a page or post by getting the post type:

get_post_type($post->ID);

It’s a page? Great. Get the page’s parent as well- like really simple breadcrumbs. This helps if you have hundreds of pages that can be named similarly.

if (get_post_type($post->ID) == 'page') {
          $posttype = 'Page';
          $parent_title = get_the_title($post->post_parent);
}

Then, if it’s not a page, but it’s an ‘event’, we’ll make sure $posttype reflects that for when it’s printed. All we’re doing here is checking to see if the result is in the categories that are used for events. You’d replace “1,2,3,4” with the category numbers. If you’re only checking for one category, you can use its name, along with plenty of other options.

elseif ( in_category( array(1,2,3,4) ) ) {
          $posttype = 'Event';
          $parent_title = "Event";
}

If none of the conditions are met, we know it’s a simple post from the blog.

else {
          $posttype = 'Blog Post';
          $parent_title = 'Blog'; 
}

Altogether, our statement is:

<?php
get_post_type($post->ID);
     if (get_post_type($post->ID) == 'page') {
          $posttype = 'Page';
          $parent_title = get_the_title($post->post_parent);
     } elseif ( in_category( array(1,2,3,4) ) ) {
          $posttype = 'Event';
          $parent_title = "Event";
     } else {
          $posttype = 'Blog Post';
          $parent_title = 'Blog'; 
} ?>

Now, I’m actually using a table to spit everything out, but note that I’ve also included Custom Fields, a nifty WP tool, to give us the event date if it’s an event. I’ve also got some basic HTML styling to illustrate what I wanted to emphasize, but this can easily be done with classes and CSS for cleanliness.  Also, since using the_category gives me funny results on pages, I have it set to print nothing under ‘Category’ if it is.

<tr>
  <td><small><em><?php echo $parent_title; ?> > </em></small>
  <a href="<?php the_permalink() ?>" rel="bookmark" 
   title="<?php the_title(); ?>"><?php the_title(); ?></a></td>
  <td><?php echo $posttype; ?></td>
  <td><small>
   <?php
      if (get_post_type($post->ID) == 'page') {
         echo '';
      } else {
         the_category(', '); 
      }
   ?>
   </small></td>
  <td>
   <?php
      echo $meta_values = get_post_meta($post->ID, 'prettydate', true);
   ?>
  </td>
</tr>

Put all together, here’s my table:

<table id="archive" cellpadding="0" cellspacing="0">
  <thead>
   <tr>
    <th>Title</th>
    <th>Type</th>
    <th>Categories</th>
    <th>Event Date</th>
   </tr>
  </thead>

<?php while (have_posts()) : the_post();?> 

<?php get_post_type($post->ID);
     if (get_post_type($post->ID) == 'page') {
          $posttype = 'Page';
          $parent_title = get_the_title($post->post_parent);
     } elseif ( in_category( array(1,2,3,4) ) ) {
          $posttype = 'Event';
          $parent_title = "Event";
     } else {
          $posttype = 'Blog Post';
          $parent_title = 'Blog'; 
}
?>

  <tr>
  <td><small><em><?php echo $parent_title; ?> > </em></small>
  <a href="<?php the_permalink() ?>" rel="bookmark" 
   title="<?php the_title(); ?>"><?php the_title(); ?></a></td>
  <td><?php echo $posttype; ?></td>
  <td><small>
   <?php
      if (get_post_type($post->ID) == 'page') {
         echo '';
      } else {
         the_category(', '); 
      }
   ?>
   </small></td>
  <td>
   <?php
      echo $meta_values = get_post_meta($post->ID, 'prettydate', true);
   ?>
  </td>
</tr>
		
<?php endwhile; ?>
</table>

Search Results
So, we now have well-explained search results, but WP is still returning them by date and not relevance. After some trial and error, I decided on using the wpSearch plug-in. Now, I can customize the relevancy of the results, which worked well on the old site.

It’s my hope that this way of handling WP’s search function will add to the discussion of how to ‘fix’ it. And I’ll admit that it must need fixing when the founding developer of WordPress, Matt Mullenweg, uses Google to power his search results instead of WP.

Want blog posts sent directly to your email?

Sign up to get emails from Logos Creative! You'll get the latest blog posts and an occasional extra email. Unsubscribe (easily) at any time.

May 22, 2010 — 2 Comments — In Blog, Tutorial, WordPress
  • Interesting adding the extra information, but you may want to use gist embeds or modify your code examples as they’re not being escaped correctly and thus most of the markup is invisible

    • Cliff Seal

      Sorry about that, Tom! I’ve patched it right up. Thanks for bringing it to my attention.