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!

62 Comments

  1. Pingback: Tweets that mention Why Custom Post Type theming is broken in WordPress โ€“ Lee Willisโ€™ Blogย |ย leewillis.co.uk -- Topsy.com

  2. Lee,

    A good write-up of one of the shortcomings of the WordPress template system.

    One of the reasons I started using WordPress was that the templates were so easy to get to grips with – partly I guess because it is based on a standard page HTML page which includes headers, footers etc. But this does cause the issue that you outline above when you want to add theme-able content via plugins while also allowing users to customise this in familiar template files.

    My thinking so far is to filter the content of single.php and use get_template_part() to include a template file in the content area. I’ve not tried it so I don’t know if it actually works?

    This is a standard WordPress theme function so it is not reinventing the wheel, and someone could potentially create a single-{posttype}.php and use get_template_part() to include the themed core content.

  3. I feel like I’ve been to hell and back with this idea. The closure that I found was to realize that in a perfect world, plugins would extend the functionality of WordPress while themes would control it’s appearance. I have been working on a rather large plugin that registers 1 CPT and up to 12 CTs and theming is one of the biggest hurdles in the project.

    One idea that I had along the way was to extend template hierarchy to recognize special files that are meant only for my plugin. Something like my_plugin-single.php and my_plugin-multiple.php. If these files existed in the theme, they would be used to create the appropriate public views. This would allow theme authors to easily provide support for my plugin if they choose to. I think that plugins should work with template hierarchy and not develop their own template systems.

    If these custom files are not in the theme, then I think it’s fine to filter the content – it gets really squirrelly on taxonomy views, but is totally possible.

    I think that the best solution in cases such as these is to release the plugin + a theme framework which displays the custom data that the plugin creates. You might be wondering “why should I make two things? Why not just create a theme and be done with it?” This is a valid argument which I will not argue against. It’s probably the smartest thing to do. I have chosen not to both as a personal challenge and because I do not want to lock users of my plugin into a theme or a “theme family”.

    BTW: Theme Family = Framework + collection of compatible children.

    • Hi Michael,

      Thanks for the comments. I think not being able to use the out-of-the-box hierarchy (Which is otherwise great) is a big flaw on custom post-types and taxonomies right now, and would love to see this addressed in future WP release – just not sure how they can do that without breaking every theme out there.

      • If themes started using get_template_part() to it’s full potential, this would not be that much of an issue. But as this is a brand new function, not many that I’ve looked at do. IMO, if this function had a filter to override the path to the file, our lives would be a lot easier.

  4. I just got word that this will be resolved in WordPress 3.1 – I think that because nobody really relies on this like we do we should keep a close eye on its progress. Can somebody dig around to see if there are any tickets in WP trac?

  5. This is a great write up, and something which I’ve not struggled against personally yet, as almost all the WordPress stuff I do is bespoke for clients as oppose to packaged up and released (although I am working on a plug-in whhich I will be releasing, but that’s another story).

    WordPress is the first CMS I started developing with, so it’s themeing system just comes as second nature to me, but lately I’ve been doing a lot of work with Umbraco and a little bit with Magento, and these take a differant approach.

    You start off with your master template which has all the common stuff across all your pages (such as the header and footer).
    You might then have a several template files extend this, which fill the gap. You might have one which is 2 columns with a sidebar on the left, 3 columns, etc. You can then go to any depth you want and have as many as you want at each level, so you only have to worry about the content you’re interested in.

    In the case of developing third party plugins, there are still some limitations with this method, such as making assumptions about the width where your template file will be inserted, but at least you’re not respponsible for for makign sure the page has everything else.

    It would be very interesting to hear why WordPress took this approach to templates over a hierachical one.

    • Yep – absolutely. The current theme hierarchy mixes up “how should the page be laid out” with “how can I render a particular content type” (Whether that content type is a post, an archive of posts, or a list of taxonomy terms etc.)

      • Oh the irony! ๐Ÿ™‚ Drupal does what you ask and that’s one reason I left Drupal for WordPress because Drupal won’t “get out of the way” like WordPress will. That said, I’ve felt the need for exactly what you ask for many times we just need to be careful that its inclusion doesn’t (effectively) turn WordPress into Drupal.

        FWIW, I’ve been creating my own template hierarchy and creating “post-{type}-{flavor}.php” files where I can specify different flavors if I need to (flavor is a term I’ve made up for this.)

  6. Every time I want to use CPTs (and I do want to use them often), I just return to Otto’s post on the matter, and reread that. http://ottopress.com/2010/wordpress-3-0-and-custom-post-types/

    Now I’m going to add your post to my “Every day arguments with WordPress” file. To CPT, or to not CPT. It’s a dilemma!

  7. Hey,
    So Lee knows I’ve been screaming more than usual over this little issue, apart from the get_template_part suggestion by Ben. I’ve worked on a solution which is similar to what @_mfields suggested to Lee via twitter (Hijacking the_content and replacing it with a different ‘template part’).
    It’s not graceful but seems to work better than any other approach I’ve tried.
    Some developers have mentioned that the WP Core know about the drawbacks of custom post types, and apparently there are numerous tickets on trac about them.. I just hope they get too them soon ๐Ÿ™ but not too soon. I don’t want to have to write the templating system a fourth time !

    Best
    Screaming Code Monkey
    ~more screaming than usual~

  8. It’s a difficult issue. By their very nature the majority of custom post types will need both a code layer (generally reserved for plugins) and a presentation layer (normally done in the theme).

    A short code might work in some cases. Creating a custom theme is definitely a solution. It seems like hijacking/filtering a theme template will work some of the time- but because of the variety of themes there will be no silver bullet.

    It’ll be interesting to see how this is solved, but for the immediate future I think this will continue to be a “custom” feature.

  9. Really, it’s not specific to CPT or CT — it’s a more general problem of the ability of plugins to add their own theme templates to the hierarchy. It’s a nifty capability, but as you point out, the plugin has no way to know how the active theme is structured. And putting aside the relatively simple problem of whether the sidebar is on the left or the right, there are all sorts of other HTML+CSS unknowns that make it pretty much impossible for a plugin to add templates that will fit seamlessly into arbitrary themes without the user’s help.

    The ability for plugins to add virtual theme directories to the environment is best used in cases when the entire theme can be hijacked wholesale. For example, mobile themes, or themes that attempt to output something other than HTML.

    So, what I’m trying to say is that it’s not CPT theming that’s broken. It’s just the idea of plugins adding theme templates to an existing theme that’s broken. But it turns out that a common use-case for using that feature is going to be plugins which deal with CPT and CT.

    As @MichaelFields pointed out, get_template_part() might be able to help out some, but it’s still so new that not a lot of themes are using it yet.

    Maybe this is why there are so many Drupal specialist out there making money on customizing sites — it’s a hard problem to generalize. ๐Ÿ™‚

    • I think the problem is that the hierarchy doesn’t separate “how is the page laid out” (As you said “how the theme is structured”) from how to display a particular type of content. There’s some weird mis-mash of stuff going on instead. The first step is to separate “how the page is laid out” from what is being displayed. What you then need is a way to say this content type is displayed in this way when it’s displayed in this context, e.g.

      a post is displayed using this template when displayed in an archive
      a movie is displayed using this template when displayed in an archive
      a movie is displayed using this template when displayed as a single item
      a movie is displayed using this template when displayed as a search result

      You’d also potentially want to differentiate between different archive types, so, you might end up with:
      post-date-archive.php
      post-category-archive.php
      movie-date-archive.php
      movie-item.php
      movie-search.php

      Obviously the standard fallback approach would be used, so if movie-item.php didn’t exist, then WordPress would fall back to item.php – so this means that a plugin can just drop in movie-item.php and everything is beautiful because, the important thing is these are just template “parts” – the site furniture should be controlled by some other mechanism (Which would probably still want to be aware of what is being displayed (single item, archive, etc.) and form what (E.g. which category, what content type) etc. – so you could change layout depending on those.

      So, maybe the top-level has “layout templates” (Controlling the Green, Yellow and Blue in my example), and there’s a content sub-folder that contains content display templates (The white in my example).

      • Right, this where get_template_part() comes into play. It lets us replace smaller pieces of the template. TwentyTen uses this to separate the loop into its own sub-template. It’s still not perfect, though. Even if you could count on a theme having a separate ‘loop.php’ file that you can override, you don’t know how the theme author structured the HTML. They might have wrapper divs with specific classes hardcoded into the template. And if you don’t replicate it closely enough, your custom loop is going to look out-of-place.

        I know that you’re talking about breaking this down even lower, to an individual post-item within the loop, which makes the problem smaller, but it will still exist. For example, does the theme use H2 or H3 for post titles? Is it HTML5? Does it put metadata before or after the content?

        It’s really a difficult problem. I know some people would blindly say, “Use a template engine like Smarty!” But that won’t fix it, either. Making a plugin which can provide specialized theming for CPT, and which will work with any theme (or even most themes) is just going to be hard.

        One approach might be to provide multiple templates, customized for various popular themes (TwentyTen, Thematic, Genesis, Thesis, Headway, etc.) and allow the user to choose one. And of course if none of those seems to fit, then they can always hire you to customize it just for them? ๐Ÿ™‚

        • I know what you mean about get_template_part – however it’s usage is optional. I guess what I’m suggesting is that the page layout “templates” should call get_the_item() in the same way as they call get_header() and get_content(). WordPress would then have a defined way (Like the current Template Hierarchy) of finding the right template. Having this explicit, and be best practice would at least mean that we could drop in the appropriately named template and have a good chance that the content would appear in the right bit of the page.

          I take your point about styling, and how we can never “natively” fit in with the look and feel of themes automatically, but that’s a different problem to now – where we can’t even guarantee that we’ll include all of the page elements and/or have the content appear in the right place relative to those elements.

          There will always be a need for local customisation, and that’s why I’m keen to have this solved at the WordPress level – as it should allow site owners to take advantage of child-themes to build their customisations without any additional work by the plugin developers, and still have the user feel safe upgrading their base parent theme and be confident they won’t lose their customisations.

          • I meant to mention this more explicitly before, but I don’t know if there can be a “one size fits all” solution. The real problem here is that trying to handle theming issues for a major chunk of content from within a plugin is just breaking out of the already-tenuous separation of content and presentation that WordPress currently has.

            That’s not even just a WordPress problem. It’s a general architectural issue that will hit pretty much any CMS.

            I know that many people would scoff at describing WordPress as an MVC system, but it pretty much is. The core is the Model (and the basic Controller). Themes are the Views. Plugins tweak/add Controllers and sometimes the Models.

            Yes, some of the “Controller” pieces are providing bits of presentation, and some themes add extra business logic, but for the most part, it is at a small enough level that it doesn’t cause problems. But when you try to do it at a bigger scale, like formatting multiple pieces of data for a Custom Post Type, you cross too many boundaries.

          • Thatโ€™s not even just a WordPress problem. Itโ€™s a general architectural issue that will hit pretty much any CMS.

            I disagree. Joomla! (For example) does not have this problem. It has a clearly defined way to structure the main page flow under the control of the site’s theme, and then asks the component (Plugin in the WordPress world) to render it’s content into the content area. The plugin only has to worry about its content, not everything else that may, or may not be on the page.

            Then it provides an easy to use mechanism for the theme to provide overrides for that content output so that (For example) themes can ship with templates for specific components (If they want to), and/or the user can override the application’s templates to better fit in with their site design.

            WordPress allows that “overriding” behaviour – but it’s unusable because the template files also have to control the overall site layout, not just the content it’s trying to display.

            The problem isn’t “I can’t style my plugin’s output to match the site” [Which I agree isn’t a problem that can be solved], but that WordPress’ current system makes plugins responsible for site layout, not just the display of the content they control.

          • Lee,

            I can’t envision a workable solution but you clearly have a vision for what would be workable. Can you modify the core of a new install of WordPress to make it do what you suggest and submit as a patch on trac so that we can see what you mean (I know, I know; I hate it when people suggest the same to me but w/o understanding a workable solution it will be harder for people to solve the problem the way you think it can be solved.) JMTCW.

            -Mike

          • I can certainly do something – although I think a core patch to implement the vision is probably a little beyond me …

            I’ll see what I can come up with though ๐Ÿ™‚

          • Yes, I over-generalized. ๐Ÿ™‚

            I’d be interested in learning more about how Joomla structures this.

            My initial thought is that the path to making this better involves extending the template-part idea and perhaps adding a few more standard core template tags. I haven’t had time to think the approach through yet, and even if we think of a solution it’s still something that would have to be “institutionalized” as a best-practice over time.

            As a quick example of what I have in mind, we currently have a bunch of separate template tags for things like the author, the category, the tag list, post date, permalink, etc. What if we had functions to declare ‘containers’ for groups of content, and a way to tie a formatting template to the containers?

            So you might have something like (pseudocode):

            add_content_group_item('post-meta', 'authorname', 'myauthordatafunc');
            add_content_group_item('post-meta', 'catname', 'mycategoryfunc');
            set_content_group_template('post-meta', 'mypostmetatplfunc');
            ...
            [h2]the_title()[/h2]
            [div]the_content_group('post-meta')[/div]
            [div]the_content()[/div]
            [div]comments_template()[/div]
            ...

            Then the ‘mypostmetatplfunc’ callback function could do whatever it needed to display the registered data items. It would use the item name (e.g., ‘authorname’ and ‘catname’) as template variables for substitution, with the associated item callback returning the micro-chunk of markup.

            It needs a lot more fleshing out, and as I said, I haven’t had time to think it through all the way, but maybe that conveys the general idea? I dunno, maybe this is overkill.

            I think to handle this in any generic way, themes will have to get a lot more complex than they are now, and we’d end up implementing some sort of domain-specific language for template rendering.

          • And now I’m realizing that I’ve kind of failed to address the core issue here, which is that the current template hierarchy doesn’t provide an easy way to let the theme handle the main layout, and let a plugin handle just the ‘content’ area.

            I think in the back of my mind, I was hand-waving that away, assuming that we’ll let themes use get_template_part() to fetch an appropriate loop template, and we would move on to the deeper levels of the problem ๐Ÿ™‚

            My apologies for getting off track.

          • @Dougal – I’ve struggled with get_template_part() because it requires the template part developer to implement the loop which just seems wrong to me.

            There are great uses for that I’m sure, but in the edge cases not the normal case so it seems it would make more sense to use let the template specify the HTML for a single post instead of for a list of posts. This is one place where I think Drupal really gets it right with their node template albeit I think their binary choice of node or list is too limiting and we could easily correct that (I forget the specific Drupal terminology; it’s been 2 years after-all!)

            I’m actually working right now with a post list shortcode I’ve developed (it’s not great but meets my needs for the moment.) I use it to create the missing “index” page for custom post types. Assuming a site for Automobiles (aka “cars”) if we had a post_type of “car” then create a post_type=”page” called “Cars” and call the shortcode as [post-list type=”car” template=”post-car.php”]. It will then call the template “post-car.php” to display each single car. (Actually I didn’t need to pass it because “post-car.php” is the default.) But I can also call with a custom named template: [post-list type=”car” template=”post-car-just-name.php”] where on another page I might want a list of just car names. (Note: This is not a great design in total, just explaining the single “node” like template which I’ve chosen to call “post-{$type}[-{$flavor}].php”)

            Anyway, I hope there’s consideration to factoring the loop out of what themers are forced to write but as I’ve got a few other wars raging right now (better URL routing, post relationships) I figure I’ll choose my battles. ๐Ÿ™‚

          • @Mike – “Iโ€™ve struggled with get_template_part() because it requires the template part developer to implement the loop which just seems wrong to me.”

            Maybe I’m misunderstanding what you meant by this. But, if you’re saying what it sounds like you’re saying, what’s wrong with something like:


            while( have_posts() ): the_post();
            get_template_part('post-item', $post->post_type);
            endwhile;

            But again, this is working the problem from the bottom up.

            I think what we need is a way to have a ‘layout.php’ template in the hierarchy. This layout file would contain the usual get_header(), get_sidebar(), get_footer() stuff, but we’d then add a get_content() call to fetch the block for the main content area. Then get_content() would be responsible for fetching the appropriate template (single, archive, etc.).

            We’d want to abstract it out a little so that we can choose alternate layouts, e.g., layout-home.php, layout-single.php, layout-archive.php, etc.

          • Weโ€™d want to abstract it out a little so that we can choose alternate layouts, e.g., layout-home.php, layout-single.php, layout-archive.php, etc.

            Yep – all in my upcoming write-up …

          • @Dougal โ€“ โ€œBut, if youโ€™re saying what it sounds like youโ€™re saying, whatโ€™s wrong with something like:”

            Now it’s me that’s trying to understand. Do you mean what’s wrong with me having to write that code or what’s wrong with that code being in core? If the latter, nothing; that’s what I’m asking for. If the former, the problem is that loops are context specific. I’d like to see a *context-free* solution so I that could reuse them because you usually can’t reuse code for a specific post type in a loop unless you code your own template hierarchy (which most WordPress designers who my clients have hired and this I have to coordinate with on a project don’t do, so I’m stuck with coordinating duplicate code to output posts all other the place.)

            I’d like to see a core function that might be something like this:


            function the_loop_template($post_template=false) {
            while( have_posts() ) {
            the_post();
            echo '';
            the_post_template($post_template);
            echo ''
            }
            }

            BTW, does it bug anyone else besides me how get_*() as a prefix for functions is being used by functions that echo output? Shouldn’t it have been “the_template_part()”?

            -Mike
            -Mike

          • BTW, does it bug anyone else besides me how get_*() as a prefix for functions is being used by functions that echo output?

            Yes ๐Ÿ™‚ However – the WordPress API is pretty inconsistent all over the place so I’d have difficulty highlighting just this ๐Ÿ™‚

            Iโ€™d like to see a core function that might be something like this:

            function the_loop_template($post_template=false) {
            while( have_posts() ) {
            the_post();
            echo ”;
            the_post_template($post_template);
            echo ”
            }
            }

            I’m already thinking similar but I don’t think the loop should be in core, but in a template. So – the main layout template would call get_page_content() which would do a template hierarchy check, and might include content/archive-post.php which would have a loop in which itself called get_item_content() which would do another template hierarchy check to find the file to display the fragment required, e.g. content/archive-item-post.php

        • @Lee – “Yes However โ€“ the WordPress API is pretty inconsistent all over the place so Iโ€™d have difficulty highlighting just this”

          ROFL! Well at least WordPress isn’t as bad as PHP itself! ๐Ÿ™‚

          “Iโ€™m already thinking similar but I donโ€™t think the loop should be in core, but in a template.”

          I don’t have strong feelings about this but if the loop is only in the theme them you cannot get any consistency across themes because other themers will intentionally bypass or just not even be aware of the best practice.

          BTW, get_template_part() is in core, right?

          “So โ€“ the main layout template would call get_page_content() which would do a template hierarchy check, and might include content/archive-post.php which would have a loop in which itself called get_item_content() which would do another template hierarchy check to find the file to display the fragment required, e.g. content/archive-item-post.php”

          So would get_page_content() be in core or in the theme?

          BTW, I’m not proposing that there be just one option that core makes available. I think it would be good if core could had a collection of options that people could use in different contexts; some which would allow the dev to code the entire loop and others that would enable them to only have to code the post. This way we get both flexibility and the guidance of implicit best practices so that it’ll be more likely that two different themers will do things compatibly.

          Also, can we finally kill this “archive” term? It makes no sense except for with blog post and even then what’s an archive? Aren’t they all just posts? (it’s always bugged me with “archive” was in the URL path.) Doesn’t “post list” make more sense? But I digress…

          -Mike

    • I love it when Dougal weighs in! He seems to always clarify the issue and gets straight to the heart of the matter!

  10. I implemented a custom post type for a client and have code on a template to display the meta fields entered for the custom post type.

    When the post is displayed everything is fine.

    When anyone does a search for any of that info all that displays on the search page is the custom post title as the custom code is not there to display the meta fields.

    • In that case you’d have to add code to (or create) search.php and add code in there specifically for your custom post type. The point of my article is that these problems are all solvable if you’re creating the post-type and you’re also in control of the theme files. The problem comes when you want to distribute code that registers custom post types, and have those displayed by a theme that you don’t control.

  11. Good article and well said! I agree with Dougal here, but wanted to offer up another idea. The way WP handles templates could be much better if we could register templates from within a plugin (in addition to the existing templates within a given theme / child theme) much like how you register scripts / stylesheets in WP currently. Now that would be cool, and allow for a plugin itself to contain additional templates that would be the default for CPTs created by the plugin (or other things, depending on the ‘scope’ of the template added).

    Anyways, lots to be done here before plugins and themes can co-exist together in this mostly uncharted territory.

    • Interesting thoughts Scott. Have you see this trac ticket where Ryan talks about registering theme files? His first mention of registration starts here:

      http://core.trac.wordpress.org/ticket/14746#comment:37

      • I read that trac ticket as part of writing my post, and wasn’t clear that it would solve what I perceive as the problem. Namely, that if I want to create a custom post type (or custom taxonomy), I need to be able to specify a template to be used to display my post’s content. However, if I’m going to distribute this code, then I need to do so in such a way that my “templates” only need to output the custom post content – not the whole page.

        Unless I’m reading it wrong – that ticket doesn’t address this?

        • Sorry, didn’t mean to hijack the thread. I was replying to Scott’s comment more than your post. I see the problem you are complaining about but I honestly don’t know how to solve it (without creating much larger problems.) Hopefully someone with more vision than me will recognize a solution that will work.

  12. I just quickly hacked a protoype method for handling partial views which is still backward compatible.

    This is a very early protoype of how it could look, so any comments are much appreciated.

    The following code replaces the if($template…) load_template($template) code at the end of wp-includes/template-loader.php

    ass the template through any filters as before
    $template = apply_filters(‘template_include’, $template);

    // If we have a master template and a partial, we’ll load that, and then load the template within it
    // Otherwise, we stick to the old method
    $master_location = locate_template(array(‘master.php’), false);
    $partial_location = locate_template(array(‘partial-single-cpt.php’), false);

    if($master_location != ” && $partial_location != ”) {
    // Manually including the master file so that the partial variable is still accessible
    // In a more polished version of this, there would probablty be a set of hooks to allow for the sequential loading of partials within the master
    include $master_location;
    } else {
    // Missing either the master partial, so just load the template file as before
    load_template($template);
    }

    What it does, is check if there is a master template, which will contain the skelaton (such as header, sidebar and footer) and if there is the correct partial template to load within it. For now, I’ve just hard coded the template I would be using, but again, the template hierarcy would know which template file to use, and it would check if there is a partial template, and use that (with the master), otherwise it would load the full blown template.

    My master template is very simple:

    Ideally, the include could be replaced with a hook which will allow for multiple partials to be loaded sequentially

    Thoughts?

    PS. As mentioned, this is intentionally a very quick and dirty prototype ๐Ÿ˜‰

  13. Personally I think the whole concept of a plugin providing a “template” for a custom post type that is automatically going to get used for the presentation side is plain wrong.

    Plugins are all about the heavy lifting under the hood code not about presentation.

    Themes are all about heavily customised presentation.

    Themes make calls into WordPress (and plugins) by using Template Tags.

    Good plugins provide template tags or work on standard action names to insert their content so that it is easy for themes to support them.

    You can never write a section of theme code in your plugin that is going to work correctly with a large number of themes

    I’m all for you providing examples of how your plugin can be used in a theme but I don’t think you should be trying to takeover the themes responsibilities.

    • The thing is, most users want to just download a plugin, install it, and see it working. Surely the best solution is to provide a semanticallly marked up piece of output with some basic styles, so it looks half decent out of the box.
      If the user then creates a copy of this file in their theme directory (based off of the sample one) then WordPress will use that.

      I can only see plugins which just do the “heavy lifting” but no styled output (or any for that matter, and just provide you with some tags/functions) will only work for certain types of functionality

      • Spot on ๐Ÿ™‚

      • If you want to do that then you are going to have to filter the_content and that will only work for simple custom post types.

        Some times more work is needed than just installing a plugin.

        This isn’t a bad thing!

        • Actually – it would have worked beautifully apart from the fact that single-wpsc-product.php needed to know what else was output on the site (ie the yellow, green and blue on my pictures).

          If it hadn’t been for that then the plugin could have created (or fallen back to) a default shipped template that would have looked acceptable on probably 95% of sites.

          As it is we have a re-engineered “theme” infrastructure, lots of workarounds, and will probably end up looking ok on about 75% of sites [Guestimate] [Because for many themes the content of a page is more than just the_content()]

    • Peter,

      Thanks for taking the time to comment. However, if what you’re saying is true, then custom post types, and providing support for single-{post_type} within the theme hierarchy are a complete waste of time. What you’re suggesting is that a plugin that implements a custom post type shouldn’t ever provide a template, but should just directly manipulate the output (Presumably via filters on the_content and friends). That means that a user can never style an applications output without resorting to code …

      Any argument about “Themes should be used for X and plugins for Y and never the twain should meet” is missing the point that WordPress has now matured to the point where people no longer want to write plugins to filter the content of their blog posts – they’re using it to build real-world applications. The only thing that can efficiently display an application’s content is the application itself – although it should provide a way for a site-owner / theme author to override that layout if they wish. Joomla! does this really, really well, and the frustrating thing is that WordPress has all the building blocks it needs to get there.

      The case in point here, that sparked all of this is the WP e-Commerce app. Trying to implement that using single-{post_type}.php from the Template Hierarchy is impossible as that file controls not just the display of the application’s content, but also the whole site – the background discussion is here if you’re interested:

      http://groups.google.com/group/wordpress-e-commerce-plugin/browse_thread/thread/1d1c804f6b27be83?hl=en

      • The point behind single-{post_type} is to allow a theme to target a post_type efficiently.

        Also, don’t forget a plugin can already take over the output using the template_redirect action if they want to.

        • The point behind single-{post_type} is to allow a theme to target a post_type efficiently.

          Agreed, but a plugin should also be able to supply a file as a starting point.

          Also, donโ€™t forget a plugin can already take over the output using the template_redirect action if they want to

          Yes, but a plugin can’t do anything sensible overriding template_redirect because it doesn’t know what site “furniture” should be output in addition to its own content.

          • I put my comment hera because I think that the peter’s comment and the Lee’s reply can drive to a standard and good solution (at least for the “average” use).

            I agree with Peter that plugins that declare custom post type could use template_redirect to privide their own tamplate (if the user/theme doesn’t provide one in the theme directory), it’s the “WP way to handle this” and for me could be acceptable.
            But, and here comes the Lee’s ponit, could be useful only if we could provide not the whole page structure, but a smaller part, the “custom post content format only”, so to speak.
            This way we could have the efficiency and granular finetuning of single-{custo-post}.php (if user/theme provide it) and a general “average” solution (provided by the plugin) that have some chance to look accaptable in many themes

            Stefano

      • I was thinking of a way to reply to Peter but you’ve articulated this better then I could have ever hoped to.

        If WordPress has all the building blocks in the right place, if Plugin developers are screaming out for this functionality, and there is no real harm in doing it, but obviously it is harming the Plugin developers (especially the ones that have invested their whole careers into developing on WordPress) then I think it is just plain irresponsible and insulting to think that a better solution that satisfies everybody might not get considered.

        Of course I mean that in the most loving and gentle way possible. But for crying out loud – we need this. You cant give us Custom Post Types and the deny us all the bells and whistles ๐Ÿ˜›

  14. Flashy linkbait headlines aside, let’s stop framing this in the context of custom post types. It has nothing to do with custom post types. It has to do with the theming system, which incidentally is an important and rather renowned feature of WordPress.

    We’re not going to tear everything out and re-do it. But there have been suggestions for making it better. There needs to be more innovation in the space.

    Some suggested reading:

    http://darylkoop.com/2010/04/06/modular-themes-organization/
    http://darylkoop.com/2010/04/06/modular-themes-why/
    http://darylkoop.com/2010/04/06/modular-themes-performance/
    http://darylkoop.com/2010/04/07/modular-twenty-ten/
    http://wordpress.tv/2010/03/06/daryl-koopersmith-rethinking-themes/
    http://core.trac.wordpress.org/ticket/12877

    • Nacin – i’m sorry if you’re taking this personally. I agree that this is all about innovation and I guess this whole thread is the result people not finding the resources they require and feeling as though they are not being heard.

      I don’t see this as being aggressive. People here are requesting help, and making innovative suggestions. We all live and breathe and love WordPress probably a lot more then most ๐Ÿ˜›

      I can only talk about our experience. For years WP e-Commerce has been criticized for using nasty hacks, 5 years ago, even less, all we could do was use nasty hacks to achieve certain functionality that our little micro WordPress community asked us for.

      Its been incredibly stressful taking criticism sometimes but I’ve had to wear it and I’ve always taken it on the chin. I’ve never spoken out about what I feel are shortcomings in WordPress because I’m committed to my core.

      Now WP e-Commerce is making a major effort to align ourselves with core (as you know) and we just want to feel as though we’re being heard. I think it’d be funny if in 1 year from now time people are giving us shit for not doing theming right (I’m just putting it out there) when we’re saying “hey would it be possible to do this now” especially when people are making noises about helping to do the code ๐Ÿ˜›

      I don’t think anybody is saying “lets to a re-write”, I think people are saying help us get a step closer to what we need. Peace bro. See ya on skype soon hopefully :))

      p.s. I feel like we’ve opened up a can of worms!!
      p.p.s I heart WordPress!!!

      • I like the conversation here, and I’ve been following it for two days. I love the innovation in the space and I think we need more of it. I’m just not convinced we’ve reached the point where it makes sense for core to act on that yet.

        Even if we allowed for modular themes in core, it’s not going to make it any easier on you for a long time, because there’s limited guarantee that the theme supports it. Keep in mind right now it can be a challenge even to expect themes to have wp_head and wp_footer. And if the theme did, it could also just as easily support some hooks, template parts, or template tags that enable you to do exactly what you want now.

        I think you know me better than to think I was taking this personally. ๐Ÿ™‚

        • Even if we allowed for modular themes in core, itโ€™s not going to make it any easier on you for a long time

          Even more reason to start now, and embed the culture before we *really*, *really* need it ๐Ÿ™‚

          Keep in mind right now it can be a challenge even to expect themes to have wp_head and wp_footer

          Presumably this would be an easy-ish thing to check at the Theme repository, and to present info showing the user what functionality support they could expect from the theme, e.g.

          () Support for plugins
          () Support for post thumbnails
          () Support for custom post types

          This should be a fairly easy set of checks (Does it call wp_head & wp_footer, Does it call any of the _post_thumbnail functions, Does it call get_item_content [Or whatever the new function would be]).

          This obviously wouldn’t help for hand-commissioned themes, or commercial themes – but I think the commercial houses would get it right anyway if it was best practice, and at least we’d have a case to say that the user’s theme didn’t support it. Most likely in the short term we’d have to support some other way (filter the_content), but it would move us in the right direction.

          And if the theme did, it could also just as easily support some hooks, template parts, or template tags that enable you to do exactly what you want now.

          Absolutely, but every theme has their hooks and filters called differently, so we can’t support them all ๐Ÿ™‚

      • I can definitely related to “not feeling heard at times.” Here’s my latest example on post-to-post relationships where the core team’s position seemed to be “it’s an edge case” (and I’m hoping you’d disagree with that assessment as I do):

        http://core.trac.wordpress.org/ticket/14513

  15. I totally understand what Peter is saying, Plugins should only do functionality, and Themes should do presentation.
    A lot of this confusion could be cleared up if someone could show us a Plugin that creates Custom Post Types and Taxonomies that uses the single-{Post-Type}.php and other templates and still caters to more than one Theme / Theme Framework, cause I haven’t found one that can do so elegantly…
    If this is right, then Custom Post Types are limited to one theme or framework.. but then, that means a Theme has to do the heavy functionality?~

  16. Another thought.

    The problem is not necessarily the lack of support in core for plugins to get deep and dirty into theming but actually the lack of support in popular themes for popular plugins.

    Ideally, the popular themes would ship with support for the popular plugins allowing the kind of deep integration you desire out of the box.

    The rest of the time I think the end-user is better served with having to do some work to customise the theme (based on examples you provide) that for you to expect to be able to insert something into the template hierarchy and it to just work.

    If template_redirect isn’t enough because you don’t know how the theme is structured then chucking extra templates from your plugin into the hierarchy isn’t going to work either.

    The alternative is to do what BuddyPress does and ship with an example parent theme which makes use of the plugin which the end-user can then customise.

    All the support for doing that is already in core.

    • Hi Peter,

      As I previous stated on this thread I still don’t have a strong opinion of what will address Lee’s concerns but one thing you wrote stands out:

      “Ideally, the popular themes would ship with support for the popular plugins allowing the kind of deep integration you desire out of the box.”

      Ignoring the tiny handful of popular plugins where it just makes complete sense to provide support that statement just feels like it is going in the wrong direction. Let me rewrite that statement using an analogy to might bring the point home:

      “Ideally, the popular homebuilders would build their homes with electrical outlet support for the popular appliances allowing the ability for you to use an appliance without hiring an electrician as you desire.”

      My rewrite presumes there is no standard for electrical outlets which of course there is and since their is we all see that statement above as addressing the issue from the wrong direction. My point is I think you are placing the responsibility for solving the problem on the wrong shoulders.

      It seems to me that it would result in far more plugins being compatible with far more themes if we could codify a standard way for plugins to support a theme because the theme calls functions that are in future core that provide the support. That would be the WordPress plugin and theme equivalent of the standardized electrical plug and outlet.

      Less, as I’m thinking through the problem again it seems more and more like the solution is what Scott Kingsley Clark suggested and that is to allow themes to register their files and layout properties, i.e. what kind of sidebars and widget areas they provide, etc. and update the widget logic so it’s no longer site-wide but instead recognizes the complexity of a theme with many different potential layouts and the fact that a plugin may want to insert items into those layouts (actually it seems that your want your plugin user to assign settings to specify where in the theme your Director, Actor, Running Time and Review information would go, but at least with theme layout registration your plugin could know what is available.)

      So Lee, would this not address your concerns?

      And Peter, is registration of theme files and layout something you would disagree with?

      Lee, is that what you are looking for?

      • Less, as Iโ€™m thinking through the problem again it seems more and more like the solution is what Scott Kingsley Clark suggested and that is to allow themes to register their files and layout properties, i.e. what kind of sidebars and widget areas they provide, etc. and update the widget logic so itโ€™s no longer site-wide but instead recognizes the complexity of a theme with many different potential layouts and the fact that a plugin may want to insert items into those layouts (actually it seems that your want your plugin user to assign settings to specify where in the theme your Director, Actor, Running Time and Review information would go, but at least with theme layout registration your plugin could know what is available.)

        Plugins already register the fact that their posts are of a different type. The problem is that there’s no way for the plugin to register “To display this item use this layout” – without also having to understand the layout of the site’s overall theme.

        So Lee, would this not address your concerns?

        Not directly – although you’ve inadvertently covered the solution, in that the theme would invoke the plugin to render “fragments” of the display. What I’m after is that the per-post-type entries in the theme hierarchy should just represent page fragments – not the entire page. The articles @nacin linked to earlier cover the rationale, and the type of solution that would work perfectly.

        http://darylkoop.com/2010/04/06/modular-themes-why/

        And Peter, is registration of theme files and layout something you would disagree with?

        Lee, is that what you are looking for?

        It’s much more complicated than what I’m looking for ๐Ÿ™‚ Your proposed solution needs mine to work – but adds a layer of (IMHO unnecessary) complexity on top.

  17. I’ve been struggling with this very thing all week and finally found an old, out of date plugin that I was able to tweak. I put this code in my main plugin file and it works like a charm:

    http://stackoverflow.com/questions/4647604/wp-use-file-in-plugin-directory-as-custom-page-template/4975004#4975004

    • Hi – I think that’s a different problem to what I was discussing – however why are you worrying about creating a file in the theme directory. If you hook into template_redirect, or page_template you can pull in the template from anywhere you like – including your plugin code if you wanted to … Hope that helps.

  18. Pingback: Hacking WordPress Templates | impleri

Leave a Reply

Required fields are marked *.