Update: We’ve created a second edition of this article, with updated code samples and coverage of the latest theme development techniques. Check it out at The WordPress Theme Search Template and Page Template. It’s part of The ThemeShaper WordPress Theme Tutorial: 2nd Edition.
The Search Template and The Page Template are vital to any complete WordPress Theme. And they’re both really easy to code. For both these two Templates we’ll start with our template-template again.
<?php get_header(); ?> <div id="container"> <div id="content"> <div id="nav-above" class="navigation"> </div><!-- #nav-above --> <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>> </div><!-- #post-<?php the_ID(); ?> --> <div id="nav-below" class="navigation"> </div><!-- #nav-below --> </div><!-- #content --> </div><!-- #container --> <?php get_sidebar(); ?> <?php get_footer(); ?>
But, of course, each one is going to take it’s own different path.
The Search Template
In search.php
we’re going to reintroduce the loop back into our Template. This time with an IF statement—in case we don’t have any posts to loop through.
Here’s how it’ll work: IF we have posts, or, in other words, if there are posts that match the terms we’re searching for, THEN loop through them, sorta just like in index.php
, but IF we don’t have posts to loop through, or, if there aren’t any posts that match our search terms, give our searchers another chance at this searching business.
In code, it would look like this:
<?php get_header(); ?> <div id="container"> <div id="content"> <?php if ( have_posts() ) : ?> <?php while ( have_posts() ) : the_post() ?> <!-- this is our loop --> <?php endwhile; ?> <?php else : ?> <!-- here's where we'll put a search form if there're no posts --> <?php endif; ?> </div><!-- #content --> </div><!-- #container --> <?php get_sidebar(); ?> <?php get_footer(); ?>
Pretty straightforward, right? Almost.
I like to keep all my index-ey Templates the same: Post Title, Meta, Content (or excerpt), Utility links. But when WordPress searches for posts it also searches through Pages, which don’t need the post meta or utility links displayed. So, in our loop, we’re going to check and see if we’re dealing with a post or a page.
<?php if ( $post->post_type == 'post' ) { ?> <?php } ?>
Wrap any code with that IF statement and it will only show if we’re dealing with a page. Now that we understand what’s going on, here’s what the #content div of our search template will look like:
<?php if ( have_posts() ) : ?> <h1 class="page-title"><?php _e( 'Search Results for: ', 'your-theme' ); ?><span><?php the_search_query(); ?></span></h1> <?php global $wp_query; $total_pages = $wp_query->max_num_pages; if ( $total_pages > 1 ) { ?> <div id="nav-above" class="navigation"> <div class="nav-previous"><?php next_posts_link(__( '<span class="meta-nav">«</span> Older posts', 'your-theme' )) ?></div> <div class="nav-next"><?php previous_posts_link(__( 'Newer posts <span class="meta-nav">»</span>', 'your-theme' )) ?></div> </div><!-- #nav-above --> <?php } ?> <?php while ( have_posts() ) : the_post() ?> <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( __('Permalink to %s', 'your-theme'), the_title_attribute('echo=0') ); ?>" rel="bookmark"><?php the_title(); ?></a></h2> <?php if ( $post->post_type == 'post' ) { ?> <div class="entry-meta"> <span class="meta-prep meta-prep-author"><?php _e('By ', 'your-theme'); ?></span> <span class="author vcard"><a class="url fn n" href="<?php echo get_author_link( false, $authordata->ID, $authordata->user_nicename ); ?>" title="<?php printf( __( 'View all posts by %s', 'your-theme' ), $authordata->display_name ); ?>"><?php the_author(); ?></a></span> <span class="meta-sep"> | </span> <span class="meta-prep meta-prep-entry-date"><?php _e('Published ', 'your-theme'); ?></span> <span class="entry-date"><abbr class="published" title="<?php the_time('Y-m-dTH:i:sO') ?>"><?php the_time( get_option( 'date_format' ) ); ?></abbr></span> <?php edit_post_link( __( 'Edit', 'your-theme' ), "<span class="meta-sep">|</span>ntttttt<span class="edit-link">", "</span>nttttt" ) ?> </div><!-- .entry-meta --> <?php } ?> <div class="entry-summary"> <?php the_excerpt( __( 'Continue reading <span class="meta-nav">»</span>', 'your-theme' ) ); ?> <?php wp_link_pages('before=<div class="page-link">' . __( 'Pages:', 'your-theme' ) . '&after=</div>') ?> </div><!-- .entry-summary --> <?php if ( $post->post_type == 'post' ) { ?> <div class="entry-utility"> <span class="cat-links"><span class="entry-utility-prep entry-utility-prep-cat-links"><?php _e( 'Posted in ', 'your-theme' ); ?></span><?php echo get_the_category_list(', '); ?></span> <span class="meta-sep"> | </span> <?php the_tags( '<span class="tag-links"><span class="entry-utility-prep entry-utility-prep-tag-links">' . __('Tagged ', 'your-theme' ) . '</span>', ", ", "</span>ntttttt<span class="meta-sep">|</span>n" ) ?> <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'your-theme' ), __( '1 Comment', 'your-theme' ), __( '% Comments', 'your-theme' ) ) ?></span> <?php edit_post_link( __( 'Edit', 'your-theme' ), "<span class="meta-sep">|</span>ntttttt<span class="edit-link">", "</span>ntttttn" ) ?> </div><!-- #entry-utility --> <?php } ?> </div><!-- #post-<?php the_ID(); ?> --> <?php endwhile; ?> <?php global $wp_query; $total_pages = $wp_query->max_num_pages; if ( $total_pages > 1 ) { ?> <div id="nav-below" class="navigation"> <div class="nav-previous"><?php next_posts_link(__( '<span class="meta-nav">«</span> Older posts', 'your-theme' )) ?></div> <div class="nav-next"><?php previous_posts_link(__( 'Newer posts <span class="meta-nav">»</span>', 'your-theme' )) ?></div> </div><!-- #nav-below --> <?php } ?> <?php else : ?> <div id="post-0" class="post no-results not-found"> <h2 class="entry-title"><?php _e( 'Nothing Found', 'your-theme' ) ?></h2> <div class="entry-content"> <p><?php _e( 'Sorry, but nothing matched your search criteria. Please try again with some different keywords.', 'your-theme' ); ?></p> <?php get_search_form(); ?> </div><!-- .entry-content --> </div> <?php endif; ?>
The Page Template
You know what the Page Template is for. WordPress thinks of it as a post out of chronological order. We think of it as, well a page. But largely, it’s defined by what it doesn’t have: all the usual trappings of a blog post.
Except comments. Sometimes pages have comments. I don’t like them there. You might one day. So we’ll have to deal with that somehow. How about with … custom fields. If you want comments on a page you can add a custom field with Name and Value of “comments” to your page. Sounds good to me.
Here’s what you’ll need to for a perfect WordPress Page Template:
<?php get_header(); ?> <div id="container"> <div id="content"> <?php the_post(); ?> <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>> <h1 class="entry-title"><?php the_title(); ?></h1> <div class="entry-content"> <?php the_content(); ?> <?php wp_link_pages('before=<div class="page-link">' . __( 'Pages:', 'your-theme' ) . '&after=</div>') ?> <?php edit_post_link( __( 'Edit', 'your-theme' ), '<span class="edit-link">', '</span>' ) ?> </div><!-- .entry-content --> </div><!-- #post-<?php the_ID(); ?> --> <?php if ( get_post_custom_values('comments') ) comments_template() // Add a custom field with Name and Value of "comments" to enable comments on this page ?> </div><!-- #content --> </div><!-- #container --> <?php get_sidebar(); ?> <?php get_footer(); ?>
How To Create a WordPress Theme
This post is part of a WordPress Themes Tutorial that will show you how to create a powerful WordPress Theme from scratch. Read it from the beginning and code yourself up something awesome.
- WordPress Theme Tutorial Introduction
- Theme Development Tools
- Creating a Theme HTML Structure
- Template and Directory Structure
- The Header Template
- The Index Template
- The Single Post, Post Attachment, & 404 Templates
- The Comments Template
- The Search Template & The Page Template
- The Archive, Author, Category & Tags Template
- The Sidebar Template
- Reset-Rebuild Theme CSS & Define Your Layouts
I like offering the comments template via custom fields. clever.
Hi,
one tip to readers. Since we don’t yet have a search field in our templates to do an actual search and see how our Search Page looks and works, we can get the same by putting this url in the browser:
http://localhost:8888/yourinstallname/?s=lorem ipsum
Replace “yourinstallname” with the name you gave your WP install (mine is simply “wordpress”) and “lorem ipsum” with the words you want to search. Voilá! Our search page in all it’s glory.
This only works if you have installed a server in your local computer as Ian recommended in the first post, of course.
Thanks for the guide so far, it’s been really useful. One question: I’m not quite sure what you mean by adding a custom field to enable comments. Could someone explain that for me?
Scroll down on the post/page write screen in the WordPress back end and you’ll see it. It’s a method of adding extra information to WordPress posts and pages.
Ah great, never knew what that was for. Thanks!
Brilliant. I plan to use these tutorials to create a theme from scratch, but for now they’re helping me tidy up an existing theme. Really appreciate all your hard work. Thank you.
Just Purchased Thematic Feature Site Theme. WORD PRSS Tells me “Template Missing” Wont allow me to load the theme. What do we do?
I’m using WordPress 2.9, and it has native support for comments switching on pages. Just go to your admin panel, edit a page, and go down, you’ll see the “allow comments” switch.
So, this lesson is outdated. Just remove the last if statement, letting the comments_template() alone. WordPress will figure out if it must be called or not.
Great, offering comments template via custom field