Solving The WordPress Template Hierarchy Puzzle: Custom Post Types

Josh Pollock - April 15, 2014

http://joshpress.net/blog/category/wordpress/tutorials/solving-the-wordpress-template-hierarchy-puzzle/http://joshpress.net/blog/category/wordpress/tutorials/solving-the-wordpress-template-hierarchy-puzzle/

Understanding the system that determines what template WordPress uses to output your content is an important step in mastering WordPress. Recently I wrote a post with an overview of learning to understand the WordPress template hierarchy. It was an introductory post on the topic. This is my first of a series of posts where I will be explaining clear, simple language each individual part of the hierarchy.

Today, we begin with custom post types. Before we begin, it is important to remember that you probably do not want to create new templates in your theme itself unless you are using a theme you developed yourself. If you add a template file, or make other changes and then update your theme you will lose your changes. This is why you should be making these changes in a child theme.

Archive vs Single View

Before we go any further, let’s make sure we are on the same page on terminology:

A post type archive is the list of all posts in a post type. The main blog index is an example of a post type archive for the ‘post’ post type. Custom post types have their own post type archives as well, if they are enabled when registering the post types. Just like with the default posts and pages, custom post types also have a single item view. This refers to when just one item, instead of the list of items is being displayed. Also, its is important to keep in mind that WordPress includes a default post type called ‘post’.

This can create confusion as it means that you can have a post in the post post type, and you can have a post in a custom post type. I know that’s confusing. That is why it is sometimes better to refer to posts as “items” that way the last part of the previous sentence could be rewritten as “an item in the post post type, and you can have an item in a custom post type.” That is a clearer and avoids the grammatically incorrect repeated word.

Templates For Custom Post Type Archives

For a custom post type archives, the template hierarchy is as follows:

archive-{post-type-name}.php -> archive.php -> index.php

For example, if you have two custom post types, ‘jedi’ and ‘planet’ and add a template to your theme called ‘archive-jedi.php’ the archive view for ‘jedi’ will be generated by ‘archive-jedi.php’ but for ‘planets’ either ‘archive.php’ or ‘index.php’ will be used instead.

Templates For Custom Post Type Single Views

The template hierarchy for custom post type single view is as follows:

single-{post-type-name}.php -> single.php -> index.php

Using the same custom post types ‘jedi’ and ‘planet’ if you added a template called ‘single-planet.php’ to your theme, WordPress would use ‘single-planet.php’ for the single item view of the planet custom post type, while falling back to ‘single.php’ or ‘index.php’ for the ‘jedi’ custom post type. Some themes include a ‘single-post.php’ template. This template is used for the default ‘post’ post type only.

Using Conditional Tags Instead Of Separate Templates

If you only need to make a small change or two to your ‘archive.php’ or ‘single.php’ for when they are being used for custom post types, it might be better to use conditional tags in the existing templates instead of adding a new template file. Knowing when it is less of a hassle to manage additional template files than to keep track of several post type conditional tags is hard to gauge, but 2 or 3 conditional tags is a good estimate.

The two conditional tags you need to know are: is_post_type_archive() and is_singular(). The first, is_post_type_archive() is used for detecting if WordPress is displaying a post type archive view. It can accept one or more custom post type names as arguments. Sticking to our previous example custom post type names, this means that is_post_type_archive() will return true for any post type archive, is_post_type_archive( 'jedi' ) would return true for ‘jedi’ post type archives but not ‘planet’ post types, while is_post_type_archive( array( 'jedi', 'planet' ) ) or is_post_type_archive() would return true for both.