This article has been retired and will no longer be updated. Caveat emptor!

— Originally Published on October 07, 2004 —

Faking Multiple Templates in WordPress

One of the things that surprised me when I first switched from Movable Type to WordPress was its lack of multiple templates. In MT you create numerous templates which allow you to change the look of different pages on your site (i.e., the homepage, archive pages, individual entries, etc.). If you want a list of your favorite links to appear on the homepage, but not on the page for an individual entry, you just delete that section of code from the appropriate template.

WordPress handles its pages a bit differently. Everything is based off of a single template, and through the magic of database queries and dynamic page generation, the right content is always shown according to which type of page you’re looking at.

The Problem

By using a single template, the default installation of WP will show the exact same sidebar on every page, and likewise, whenever you view an entry listing, it will always look the same. This one-template structure is viewed as a blessing to some, but an over-simplification to others.

What if you want to show a list of just the entry titles on your archive pages, rather than the entire entry itself? What if you want to hide the sidebar’s calendar on your individual entry pages? There are countless scenarios like these that require a little more flexibility than the default index.php file can give you.

This issue has been discussed many times on the WordPress support forums, but I’ve found most of the proposed solutions to be less than ideal. It’s rumored that the functionality to control these types of things will be built into WordPress 1.3, but for the time being, it seems we’re on our own.

A Common Solution

Many people suggest using .htaccess rules and simply forward visitors to templates other than index.php. I feel this method over-complicates things, and here’s why:

  1. It creates duplicate code when most of the time you’ll have the exact same basic page structure in each template. Not only that, but multiple templates aren’t very easy to maintain if you ever need to change that underlying structure.
  2. There’s no guarantee that all WP users will be able to create, edit, and use .htaccess files. Some hosting companies just don’t allow it.
  3. Writing .htaccess rules can be downright confusing!

My Solution

Using some simple PHP and the functionality that’s already built into WordPress, you can easily control what appears on different page types without having to create multiple templates. The key lies in exploiting a few under appreciated variables…

$single, $cat, $m, and $year are all built in variables used by WP to determine information about the type of page you’re looking at. The $single variable corresponds to individual entry pages, the $cat variable to categorical listing pages, $m to monthly listings, and $year to yearly listings.

When you’re viewing each variable’s corresponding page type, only that variable will be assigned a value. If you’re viewing the main page of your site, then none of those variables will be assigned a value. Thus, a simple test of whether or not each variable has a value can be use to control exactly what is displayed and when. Here’s the basic idea:

if ($single) {
    // individual post contents
} else if ($cat) {
    // categorical listing contents
} else if ($m) {
    // monthly listing contents
} else if ($year) {
    // yearly listing contents
} else {
    // main page contents
}

All you have to do is place the content you want to appear in the appropriate spot. If you don’t want to do anything different in a particular section from how WP handles it by default, just leave out that variable’s test.

How to Apply It

Using one of the scenarios from above as an example, let’s say that you want to show just the entry titles when viewing a categorical listing. All you’d have to do is change the <div id="content"> section of your index.php file to be something like this:

<div id="content">
    <?php
    if ($posts) : foreach ($posts as $post) : start_wp();

    if ($cat) { ?>
        <h3 class="storytitle" id="post-<?php the_ID(); ?>"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link: <?php the_title(); ?>"><?php the_title(); ?></a></h3>
    <?php } else { ?>
        <?php the_date('','<h2>','</h2>'); ?>

        <div class="post">
            <h3 class="storytitle" id="post-<?php the_ID(); ?>"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link: <?php the_title(); ?>"><?php the_title(); ?></a></h3>

            <div class="meta">
                <?php _e("Filed under:"); ?> <?php the_category() ?> &#8212; <?php the_author() ?> @ <?php the_time() ?> <?php edit_post_link(); ?>
            </div>

            <div class="storycontent">
                <?php the_content(); ?>
            </div>

            <div class="feedback">
                <?php wp_link_pages(); ?>

                <?php comments_popup_link(__('Comments (0)'), __('Comments (1)'), __('Comments (%)')); ?>
            </div>

            <!--
            <?php trackback_rdf(); ?>
            -->

            <?php include(ABSPATH . 'wp-comments.php'); ?>
        </div>
    <?php }

    endforeach; else: ?>
        <p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
    <?php endif; ?>
</div>

The process would be just as easy to change what appears in the sidebar of your page…just edit the <div id="menu"> section. Once you get the hang of it, these variables can be used to manipulate just about anything.

Taking It a Step Further

Adding in code for each of these page types can get confusing really fast. With that much information packed in to one file, the scanability of index.php drops considerably and it becomes difficult to find what you want when you need it.

To combat this, I’ve taken the fake template concept a step further…rather than listing all of the code directly in index.php, I use PHP includes to import each custom section from an external file. Rather than make this tutorial any longer than it already is, here’s how I set it up:

<div id="content">
    <?php
    if ($posts) : foreach ($posts as $post) : start_wp();
        // Faking multiple templates
        if ($single) {
            require('includes/single.php');
        } else if ($cat) {
            require('includes/category.php');
        } else if ($m) {
            require('includes/month.php');
        } else if ($year) {
            require('includes/year.php');
        } else {
            require('includes/main.php');
    }
    endforeach; else:
        require('includes/nomatches.php');
    endif;
    ?>
</div>

In the external files themselves, simply put what content you want to appear, and that’s it! I hope this helps some of you guys out.

This article has been retired and will no longer be updated. Caveat emptor!