Lee Willis

Why Custom Post Type theming is broken in WordPress

| 62 Comments

I’m not normally a fan of sensationalist headlines, but in this case I know a bunch of people have put a bunch of effort into trying to make something work “The Right Way”[TM] only to discover that the right way doesn’t actually work.

It’s even worse than that, because the same issue also affects Custom Taxonomies.

Now, much has been made of Custom Taxonomies, and of Custom Post Types, and rightly so. Custom Post Types and Custom Taxonomies are great facilities that really start to move WordPress away from a blogging tool, and into the realms of a a CMS and application development framework.

I’m a big fan of Custom Taxonomies, and I’ve written about what you can do with them before, and I’ve used them in anger on real WordPress sites. Custom Post Types are a little newer, and I’ve only just started working with them.

So – why the outrageous statement about them being broken?

Well, the good news is that I don’t think Custom Taxonomies, and Custom Post Types themselves are broken – what is broken is the theme support that goes with them.

Anatomy of a WordPress theme

To explain this in detail, you first have to understand a little about how WordPress themes work. Themes in WordPress consist of a number of files, which will be used according to the template hierarchy. That is, if WordPress is trying to display the home page it will look for home.php. If it’s found in the users theme (or child theme) then it will be used to display the page. If WordPress is displaying a single post then it will look for single.php and use that to display the page.

The important thing to note is that each of these pages, whether it’s home.php, single.php, archive.php or page.php is responsible for the whole of the page. Let’s consider an example of a web page layout from a typical website:

Breaking this down, there are the following main areas:

In this example, the page is made up of a site header (Yellow), some sidebars (Green) and a site footer (Blue). The main article/archive is contained in the white section. This is a fairly typical layout. If you were building this in WordPress, a fairly common approach would be to call get_header() at the top of all of your template files, get_sidebar() after that, then have the code to display the page content, and finally a call to get_footer().

get_header(), get_sidebar() and get_footer() are really just convenience functions that include specific theme files, making it easy to have standard headers, footers, sidebars etc. across your whole site.

So, this leaves us with this:

Custom Post Type Theming

So – what’s all this got to do with Custom Post Type theming then? Well, those of you paying attention will have realised that the Template Hierarchy provides support for theming both the display of single posts of a custom post type (Via single-{post_type}.php) and archives of posts belonging to a custom taxonomy (Via taxonomy_{taxonomy}.php or taxonomy_{term}.php).

On the face of it, this all seems fine. If you’re building a site, then you write a small chunk of code to register your custom post type, maybe add some meta boxes to the admin page to capture information specific to your post type, then throw together a template page to display it all.

Let’s take a custom post type of “Movie” as an example. We’d register it, set it up, and probably add some additional information beyond just the main content, particularly we might associate the post-type with the “Director”, and “Actor” taxonomy. This would allow us to show information about the director, and actors involved in the film on the “Single Movie” view – as well as create taxonomy archives by Director, or Actor.We might also add a meta-box to capture the movie running time, and maybe a review score (“9/10” etc.)

So, we wander off to our theme, copy single.php to single-movie.php and add in some code to fetch the taxonomy information, and display it where we want, and also to fetch and display the running time, and review score.

Job done.

The Problem

What if you’re writing a plugin that implements the movie Custom Post Type? Your end-user’s theme won’t have a single-movie.php file – so WordPress will fall back to using single.php – which of course won’t pull back the Director, Actor, Running Time and Review information. So what do you do?

The obvious thing is to supply a single-movie.php that the user can use. Now rewind a little, to where I said that theme files were “responsible for the whole of the page”.

This is where we hit our problem. We can assume that our single-movie.php should call get_header(), get_sidebar(), display our custom post type data, and then call get_footer().

But what about people who have a right-hand sidebar? What if the users theme has a bunch of standard page-furniture that isn’t included in header.php or footer.php, but included in each of the various single.php, archive.php?

Now we start to see the problem. It’s virtually impossible to distribute code that registers a custom post type, and be able to use the Template Hierarchy to display it – your only real option is to let WordPress fall back to single.php and then filter the_content, and then build your own “theme” infrastructure to let users “theme” the content.

This is bad because it’s reinventing the wheel, bad because it makes it difficult for theme authors to provide support for your cool plugin out-of-the-box, and bad because it’s unintuitive.

The same problem exists for taxonomy_{taxonomy}.php as well so you can’t create nice taxonomy views for the taxonomies your plugin creates.

Ideally, we want to be able to provide a template that is just responsible for displaying the post itself, (ie the white box only in the images above), and have the rest of the page displayed by other files in the user’s theme.

How we get there is beyond me though … answers welcome below!