WordPress Bits

Hacking WordPress. Keeping the bits together.

Making WordPress themes III : template hierarchy

Posted by Leonid Mamchenkov on August 22, 2007

(This is the third post in “Making WordPress themes” series. If you missed the previous two, here are the links: “Making WordPress themes I : static basics” and “Making WordPress themes II : The Loop” ).

In this post we’ll see which filenames WordPress recognizes in the theme directory, and how it knows which posts to show to the visitor based on where the visitor is.

Hopefully by now you’ve looked through the source code of a few WordPress themes. While each and every theme is unique, there are parts which are common among all themes. One of the common things that you probably noticed, is how themes are separated into files – index.php, category.php, search.php, single.php, home.php, etc. Practically any theme out there use some combination of files with common names. Those themes that don’t use any files or use just a few, usually apply a different technique – they have conditional statements like is_home() or is_page() within index.php.

The questions you probably asked yourself at some point were – “Which filenames does WordPress recognize?” and “Which other conditions similar to is_home() or is_page() can I use?”. And if you have a really inquiring mind, you probably also asked “What happens if I use different, non-standard filenames?” and “How does WordPress knows that a visitor is looking at search results and not archives?”.

The answers to all those questions lie in WordPress template hierarchy. While it looks like yet another Codex page, don’t be mislead. This particular page is priceless. It’s The Holy Grail of WordPress theming. Mostly, because of two things – a diagram and a link to Conditional Tags page. The diagram alone is so precious that I’ll have a copy of it here, just in case it disappears from Codex.

WordPress Template Hierarchy diagram

This diagram, just in one little drawing, tells us most of what we need to know about organization of WordPress themes. Let’s take a better look.

On the left side, we have the visitor, coming to the WordPress web site. The visitor can navigate to a number of pages – front page, full post, full page, category, author page, date-based archive, search results, and even a non-existing page. WordPress knows where the visitor is based on the URL which is used to get there. You can see from the diagram that WordPress understands both fancy URLs as well as URLs with parameters.

For each of those location, our theme can have a separate template file. WordPress checks if that file exists, and uses it if it does. Otherwise it falls back on to the next template file in the hierarchy, and checks for its existence, and so on, and so forth, until either a file is found or an index.php is reached.

So, from the diagram, if you want to separate the code for displaying the front page from everything else, use home.php . Or use is_home() conditional tag in index.php . Use single.php or is_single() condition in the index.php for single posts. And so on.

As you can see (from the diagram again), there is a very flexible way of controlling what happens when a particular post, page, or category is displayed. For example, you can have different logic and presentation for category with ID 5 from the one with ID 6.

Do we have to separate our theme into files? No. We can do everything with just conditional tags from within our index.php. But the truth is that if done this way, our index.php can often get rather large and complex, with a lot of conditions, and difficult to maintain. To make things simpler we probably should use multiple smaller files.

While we are on the topic of filenames, I think it’s good to look also at Include Tags. Include tags cover a few more filenames, which are recognized by WordPress, but not documented in template hierarchy. header.php, footer.php, sidebar.php and comments.php can be easily included from your other theme files by using calls to get_header(), get_footer(), get_sidebar(), and comments_template() respectively. Also, note that there is some magic about the comments_template() call:

This tag includes the file comments.php from your current theme’s directory. If that file is not found, it will instead include wp-content/themes/default/comments.php. To display comments on the main index or archive pages, you’ll need to set the $withcomments variable to “1” before calling this tag.

Last time, when we talking about The Loop, we mentioned that there was some magic about how WordPress knows which posts to show. I hope now you see how that magic is done. The core of The Loop is the have_posts() function call. Because WordPress recognizes the current visitor location from the URL, have_posts() knows which posts it should get – the ones in archives, the ones in the category, the ones on the front page, or the ones in the search results.

Now we know how theme part of WordPress works. In the next post we’ll see how we can control and modify WordPress behavior using The Query.

38 Responses to “Making WordPress themes III : template hierarchy”

  1. Andrew B said

    Leonid,
    Absolutely awesome series so far. You’ve inspired me to create my own theme from scratch. Its just a glimpse of hope at the moment, but I’m sure that as your series continues, so will my inspiration.

    Great work,
    Andrew

  2. Thanks Andrew.

    I’m glad there is some use to all this writing. :)

  3. XIII said

    Sweet, this keeps getting better and better.

  4. […] Entre todo el laborioso trabajo que están haciendo la gente de WordPress Bits y sus “Making WordPress Themes“, una guia bastante completa sobre como hacer un theme para WordPress, han publicado la jerarquia de un theme WordPress. […]

  5. XIII,

    hehe… there is not much left though :)

  6. XIII said

    I don’t know, I see amazing themes with lots of customisations which’ll make the average beginner blink. Explaining the loop is one thing, showing how incredible flexible it is and how you can twist it in various ways to make it do all kinds of funky stuff is another.
    Maybe a followup series? ;)

  7. XIII,

    there will be one more in this series. It should bring all the stuff mentioned before together. Including how to control The Loop and how to have more than one of them on the same page. ;)

    But other than that, I don’t think there is anything to it. Maybe I’m wrong. We’ll see.

  8. Paul said

    Leonid,

    Thanks for ALL your posts about themes and your series on plugins. They have been very informative. Hopefully I’ll be able to grok it all and use it successfully

    Thanks

  9. Paul,

    you’re welcome. If you have any problems along the way, feel free to use the comments. There are a few people here, who know WordPress enough to stretch a helping hand. :)

  10. Kahi said

    Nice to watch your series Leonid, although I’m quite outside of the goal-group :-).

    Perhaps I could link related: a scheme of theme folder, made by me.

    So… I’m lookin forward to the next part ;).

  11. Kahi,

    thanks for the link. Wow, you have a lot of cool stuff over there. In fact, I think that deserves some attention (the post is coming shortly)… ;)

    By the way, if you had a category for English language only tutorial/tip kind of posts, I’d be interested in adding the feed to it to the sidebar of the WordPress Bits.

  12. Kahi said

    Oh, Leonid, I’m really surprised that you like it (so much :-)) because that blog is actually at it’s beginning… As you can see, many things are missing, navigation, taxonomy, … many things. Could you please stay tuned until I recover the site with a… design? :-)

    Sorry, the en-feed I will prepare after redesing, now it’s redirecting to feedburner-feed with all cats… :-\

    I will let you know surely ;).

  13. Kahi,

    OK, no problem. Take you time ;)
    You do have a nice start there.

    P.S.: please don’t change anything in the next 12 hours or so. I have a suspicion that a few people will want to check it out as it is.

  14. […] Making WordPress themes III : template hierarchy. Now, why couldn’t someone have written this a year ago? I’ve had to figure all this crap out on my own. This entry was written by Ben and posted on at 11:32 am and filed under url. Bookmark the permalink. Follow any comments here with the RSS feed for this post. Both comments and trackbacks are currently closed. No Tags « Forget Something? […]

  15. […] Making WordPress themes III : template hierarchy (This is the third post in “Making WordPress themes” series. If you missed the previous two, here are the […] […]

  16. […] Making WordPress themes III : template hierarchy (This is the third post in “Making WordPress themes” series. If you missed the previous two, here are the […] […]

  17. mharacz said

    interesting read, thanks

  18. Awesome series! I’d definitely be taking note of the lessons taught here and apply it through improving the theme design for my blog. :D

  19. Leonid, I’ve got a question – do you know which file is responsible for “domain/page/2” pages?
    Spasibo :)

  20. Cigar Inspector,

    it looks like you are looking at the second page of front page posts. If you are not sure, you can disable fancy URLs in Options->Permalinks (use the default one with question marks).

    If that’s front page, you should look for home.php file and if it is not there, then index.php .

  21. I asked because I am using the SEO Title Tag plugin and these pages are the only ones that do not seem to be affected. So I thought that perhaps they called different headers (not with the get_header function). Tried a lot of things already, and everything failed.

  22. engtech said

    I really appreciate the guides you’ve been writing.

  23. Cigar Inspector,

    I’m not familiar with the plugin, but you can check its source for conditional tags. If there are things like is_home(), is_single(), etc, then try putting one for is_paged() and see if it makes any difference.

  24. […] Making WordPress themes III : template hierarchy […]

  25. […] nos vamos entendiendo, una imagen vale más que mil palabras. Archivado en: CMS minipost programación […]

  26. Kevin said

    @Cigar Inspector:

    Are you talking about the function that makes the “pretty” URLs in the address bar? If so that’s in the .htaccess file that is probably in your hosting root folder. You can edit the file from Manage > Files > .htaccess(for rewrite rules) if you want, but if you don’t know what you are doing you could possibly cause any requests for your index.php to result in a 403 or 404 response.

    Personally I just use it for blocking scraper bots from pulling content from sites I administer, or rewriting the URL to remove www when people place it in their address bar.

    As for SEO purposes, I would suggest just using /%category%/%year%/%monthnum%/%postname%/ as your permalink structure, or perhaps removing the year and month to just have /%category%/%postname%/. Besides the permalink is going to be more for a human visitor than a spider on its initial crawl through your site. You shouldn’t change the permalinks however since most search engines cache previous crawls for some unpredictable amount of time which could result in someone getting a 404 page instead of the content they searched for in Google.

  27. […] looks first for special files and then defaults to the index.php file (as shown in this diagram). We can take advantage of this by using only an index.php file and then using conditionals to […]

  28. […] Making WordPress themes III : template hierarchy « WordPress Bits Jerarquia de los PHP de WordPress. Hay varios que no conocia. (tags: wordpress php howto tutorial) […]

  29. […] looks first for special files and then defaults to the index.php file (as shown in this diagram). We can take advantage of this by using only an index.php file and then using conditionals to […]

  30. @Kevin:
    Thanks for your input, but I was actually talking about the Title tags. I have permalinks set up and I am satisfied with them. (I use category/postname). I just fail to understand why I manage to customize the titles on ALL the pages except the ‘page/X’ ones!

  31. […] side of blogging, should take a look at the WordPress Bits blog. It’s a wide (and occasionally deep) exploration of how the WordPress blogging software […]

  32. […] (This is the third post in “Making WordPress themes” series. If you missed the previous two, here are the links: “Making WordPress themes I : static basics” and “Making WordPress themes II : The Loop” ). In this post we’ll see which filenames WordPress recognizes in the theme directory, and how it knows which posts […] Continue… […]

  33. Aizat said

    I will try creating my own theme and I hope you will be able to help me if I have question and problems. Thanx a bunch!

  34. […] Making WordPress themes III : template hierarchy « WordPress Bits […]

  35. ambj said

    cool..!

  36. Vishal said

    Hi,
    The article is really good and it help me figure out what I was looking for.

    May be I am missing out something or am an idiot.But here’s my problem

    I have a wordpress blog.
    It works fine. What I am trying to do is have another menuItem (Movies which i have added successfully)
    Now what I want is when ever user clicks on “Home” it shows the list of all recent post.( workd fine)
    And when user clicks on Movies – I want to show all the posts posted in “Movies Category” same way as in “Home Page”

    This is what I have created:
    1)added a page2.php in template
    2)When movies is pressed in menu I call page2.php but it shows only one post.
    How do i tell it to fetch me all the postes in “Movies Category”

    Any help would be appericiated.

    Thank you

  37. benz001 said

    Firstly thank you, this diagram has helped me so much – however its now superseded by the WordPress codex version (which is always kept up to date) and this blog post page is still coming up in google.

    So look here -> http://codex.wordpress.org/File:Template_Hierarchy.png

  38. Kemal ONUR said

    Thank u so much.

Leave a reply to Kemal ONUR Cancel reply