Including a WordPress Page Template in a Plugin

Note that this plugin is just a working proof-of-concept. Do not use this in a production environment.

One of the challenges of working with templates within the context of WordPress plugin development is that there’s no easy way to bundle templates with your plugin and register them with WordPress.

Template are usually relegated to theme development. And rightly so, correct?

After all, page templates are used to provide layout and presentation which is precisely what themes are meant to provide.

But if you’re working on a larger, more complex plugin that introduces custom post types, page templates, and other advanced functionality then there may be a use case in which bundling templates with your plugin is necessary.

I’ve hit up against this exact issue in a recent project, so I thought I’d share the basics of how I solved the problem, and then provide an example plugin to make the process of registering page templates with WordPress themes a bit easier.

On The “Page Template in Plugin” Discussion

I’ve shared this before, but I generally believe that themes should be dedicated to providing presentation and layouts for data, and plugins should be responsible for introducing functionality into WordPress.

The thing is, the lines can get blurred (and often are). Personally, I think that we – as designers and/or developers – blur the lines more than we should, and that’s another post for another time, but there are times where a plugin may need to include a page template, or a theme may need to introduce some custom functionality.

Thanks to things such as the Settings API, it’s relatively easy for themes to introduce functionality, but it’s not as easy for plugins to introduce presentation functionality.

Case in point: It’s not easy to include a page template with your plugin and register it with WordPress.

There has been a fair amount of discussion about this on the web, and even some relatively complex solutions that can be achieved at the code level.

Usually, I’m all for programmers using whatever solution solves their problem (so long as it’s not a complete abomination of code :), so I thought I’d share – and open source – an example plugin for how I’ve gone about solving this problem.

The Page Template Example Plugin

Page Template Example Plugin

The Page Template Example Plugin on GitHub (ready for pull requests!)

The Page Template Example plugin is an extremely simple plugin used for demonstration that distills one strategy for including templates with your plugins and registering them with WordPress.

Straight from the README:

An example WordPress plugin used to show how to include templates with your plugins and programmatically add them to the active theme.

The way it works is quite simple:

  • The template is included with the plugin
  • When the plugin is activated, a copy of the template is written to the active theme’s directory
  • When the plugin is deactivated, the template is removed from the active theme’s directory

Technically, this works by basically creating an empty file in the active theme’s directory, reading the contents of the template in the plugin, then writing it to the file that was created upon plugin activation.

A Word of Caution

This plugin is meant for demonstration purposes only which is why I’ve tagged it as 0.1. Think of it as a proof of concept.

Sure, it can be made more robust with enhanced error handling and functionality and I’d love to see a few of you create some pull requests, but until then I recommend avoiding using this plugin in production environments.

If anything, use it as a starting point off of which to build more advanced functionality.

Known Issues

To be clear, there are known issues that I cover in the plugin’s README. Ultimately, I’d love to see these issues added or resolved in a future version of the plugin.

If I have time to continue working on this, I will; however, if you have time, feel free to add your commits as well.

Anyway, the known issues are:

  • If the user changes a theme, the plugin does not move the template to the new theme’s directory.
  • There’s practically no error handling for the file operations.
  • If a template with the same file name already exists, there’s no notification or error handling in this case so the user has no idea that the bundled template was not activsated.
  • …and more to be discovered.

Again, this is more-or-less a proof of concept as showing one way in which you can add templates to your plugin and have WordPress easily recognize them.

Add To It!

Since this plugin is nothing but a simple, working proof-of-concept, feel free to add to it – I’m open to any and all improvements that you guys want to add.

The purpose of getting an 0.1 out on GitHub was to show that it is possible to include templates with plugins and register them with WordPress without having to introduce any sort of hacky-work around.

Secondly, there are far more talented WordPress programmers that I’m hoping will initiate a few pull requests so that the plugin reaps the benefits, and so that I – anyone else who reads the blog or the plugin – learns from them.

So have at it :).

41 Comments

Super useful. Thanks for this, going to throw it into a recent project and potentially can whip up some fixes for known issues….

    Sure thing – getting some additional fixes in there (because, again, this is a strict 0.1 proof-of-concept idea) would be great.

    Exactly what I was hoping for from you and the rest of the guys :).

Wow, you were just “that” close – I just finished a plugin for a project I’m working on that I included 2 page templates in. Although I didn’t go as far as moving the plugin templates to the current theme. What I decided to do was to take a simliar approach to other plugins like WooCommerce and All In One Events where they include default templates and the developer/designer can pull those templates out and include them in the theme. If they don’t do that step, then the default templates inside the plugin will be used.

I like the idea of the moving the files automatically though and would be very helpful too.

    I completely agree, I think the best way to go is to create default templates in the plugin directory that are overrode by templates in the theme

    I recently did a project with WooThemes Sensei plugin that used this process, it was beautifully easy to customize, and if you broke something can simply delete your custom page template or copy over the original again.

    I am currently building themes that work hand-in-hand with custom plugins. Using this technique I feel that it offers the greats flexibility for theme designers to add custom styles to a plugin with no update conflicts.

    Although it does introduce the issue of fragmentation when adding functionality in an upgrade as the legacy template attached to the theme may not have all of the calls necessary to display new features. Some work will need to be done in the way of checking template version numbers, and creating an admin alert that imforming the user that “Your custom page template is outdated and must be updated for features _____ & _____ to display.” or somthing to that effect.

    …they include default templates and the developer/designer can pull those templates out and include them in the theme.

    I think that works great exactly for developers and designer. When they’re your customer, that works.

    But when you’re targeted the more average user who knows how to use templates, but don’t necessarily know anything about moving files around from wp-content/plugins to wp-content/themes, then it’s an entire different use case.

    At any rate, the plugin needs to work, but it’s a starting point. At least until this trac ticket is folded into core.

This looks like a good example of how some plugins handle the problem that you described but there is a solution under way on WordPress trac: http://core.trac.wordpress.org/ticket/22355

The solution that’s being discussed is to allow plugins to register templates to the template stack. This will make it possible to overwrite a template in a parent or child theme as in this theme was in “parent/parent theme” ( if that makes any sense )

Your code might still be useful to make it easy to pull templates from plugin into the theme.

A few months ago, I wrote a library that does what “ticket/22355″ proposes. You can see it here: https://github.com/wrktg/scaleup-templates
There is a fairly good description of how to use it.

    The solution that’s being discussed is to allow plugins to register templates to the template stack.

    Exactly. That’s what needs to be made possible, so I’m eager (and excited) to see this coming in the next release.

    Although the code may be useful, it’s not without its issues, so hopefully I’ll got some additional time or we’ll get some other pull requests in their to make it more resilient than as it currently stands.

I like the idea, but not so much the execution. First of all, copying files into the theme is not really a good idea. On the one hand, what happens if the theme updates after your plugin is installed? You’ll lose the copied template. On the other hand, what if the server is locked down and requires FTP access to work with the filesystem (the WP_Filesystem API handles this for plugin installation and updates … without that, your @fopen calls will fail silently).

An alternative I’ve used is to rely on locate_template() to see if your template file is included in the theme. If it is, great! Use the theme’s version. If not, you can include() a version of the template that’s bundled with the plugin instead. Just hook things to template_redirect and you’re not stepping on WordPress’ toes.

    These are all completely valid points. I don’t really disagree with them, but I do think there’s room for some of the cases to be handed.

    Case in point: There are ways in which you could programmatically store the theme version and, when it’s changed, re-apply the template.

    Secondly, you could also make sure that you’re able to “deploy” the template from some type of configuration interface from the dashboard. Honestly, I have mixed feeling about introducing like this because it feels a bit too complex for something that should be trivial, but it’s an option nonetheless.

    On the other hand, what if the server is locked down and requires FTP access to work with the filesystem (the WP_Filesystem API handles this for plugin installation and updates … without that, your @fopen calls will fail silently).

    If this is the case, then a person is better off working with their own consultant or developer to build them a more tailored solution. I hope that doesn’t sound like a cop out :).

    For template_redirect, correct me if I’m wrong, but that doesn’t register the template with the page editor’s template dropdown menu does it? That’s mainly the point for this plugin: It’s to bundle a template with the plugin and then register it with WordPress so that users can select it from the ‘Page Template’ dropdown.

    I know this has been discussed in a later comment, but I’ll get to that momentarily.

I think Edward, Jason and Eric have hit the nail on the head – let WordPress choose the template and you can decide if you want to over-ride it – though you’ll want to use the template_include, rather than template_redirect hook for this! You can see something similar in action here: https://github.com/stephenharris/Event-Organiser/blob/1.7.3/includes/event-organiser-templates.php#L193

But there is a minor hiccup with page templates. Unlike post type templates (which I think is the basis of Edward, Jason & Eric’s suggestion), page templates are selectable from the admin screen. And last I checked there is no nice way of including your plugin-residing template into that dropdown list. So without your template actually existing in the theme there is no non-hacky or non-UI-wrecking way of including your template among the choices.

If we could have a filter in get_page_templates() – we’d be sorted :)

    Stephen pretty much ticked off all the points I was going to make.

    Beyond that, I don’t think plugins should be writing to the theme directory in general, unless it’s a manual action (click to copy, etc). Removing on deactivation is especially troublesome because any customizations would be wiped out.

    The only benefit I see to this approach is that it allows page templates to show in the dropdown. In that case, I’d think inserting an option via jQuery and filtering the save/display routines would be a little less error-prone. A core filter would be nice, though.

      Beyond that, I don’t think plugins should be writing to the theme directory in general,…

      In general, no, but for specific projects? I think there’s a strong enough use case for it. After all, this has stemmed from a client project I’ve been working on for the last month or so.

      I’d never say that this is something that we need to be doing across the board. It blurs the lines between presentation and functionality too much.

      But to your point on “inserting an option via jQuery:” I’ve considered this, but there’s a number of problems (some more subjective that others):

      I generally try to find server-side solutions before jumping into client-side solutions
      We’re all well aware of just how easily other developers can break theme and plugins by doing funky stuff with jQuery so it’s more more reasonable to assume that using the server-side to handle this is safer than using a client-side solution.

      Finally, doing so on on deactivation is just part of the demo. This isn’t meant to be a definitive solution by any means.

      I do think we’re all in agreement though: A core filter could benefit us all greatly :).

    See my comment here for why issues with template_include or template_redirect.

    But you’ve really already hit on it: it’s registering it with the dropdown menu on the page editor and that’s what I’m trying to accomplish with this example.

    I agree with you – if we had get_page_template, we’d be gold, but until then…

Good call. Filtering on template_include instead will have the same effect, but will forego skipping the HEAD request check WordPress does (so it will be more performant).

I think everyone covered my problems with this approach already. But worth mentioning: if you’re going to write a file to the theme directory, make this very clear and obvious in the plugin description! Or even go so far as to add an additional step to the activation process where the user has to click a button for the file to be copied.

Very little will make me stop using a plugin quicker than doing something jarringly unexpected like writing a file to my theme directory.

That said, I wish WordPress had a better templating system in general.

    Very little will make me stop using a plugin quicker than doing something jarringly unexpected like writing a file to my theme directory.

    Oh, I definitely agree. In previous posts, I’ve spoken at length about making sure that we – as developers – don’t create an experience that interrupts what the user expects to happen versus what actually happens.

    These comments have prompted me to add a note to the header of this post as that this is just a prototype plugin.

    That said, several things have been brought up that I think would make for some useful additions to the plugin – such as adding an option or a page for having the user activate move the template, or use jQuery to add the template (though I’m personally not a huge fan of the approach, I don’t want to ignore it as a viable option).

    Maybe I’ll look into doing this for a 0.2 release :).

    That said, I wish WordPress had a better templating system in general.

    Agreed. Apparently improvements are in the pipeline for 3.6. Can’t wait – hopefully this will be made obsolete by then!

A page templates solution was on my to do list too, it’s sorely needed. I was thinking more on the lines of a template_redirect solution and replacing/creating an alternative template dropdown with a nicer ui (could even show visual icons showing the layout). I’m so glad to see Ticket 22355 though, hope it makes it in on the next release.

    Yep – same here. This particular plugin is obviously experimental, but I still may add a couple of solutions based on what others have proposed as well if for nothing else than kicks and giggles.

I’d like to point out that the trac ticket that keeps being referred to ( #22355 ), is not a solution. That trac ticket is only concerned with allowing plug-ins to ‘inject’ themselves into the template hierarchy (which you can kind of do already with template_include) – but more importantly to inject themselves into ‘child templates’ (i.e. templates called from within other templates via locate_template()).

So that ticket only makes the part of the problem we can already solve only (very) slightly easier.

The problem is in fact (not) being able to filter get_page_templates().( See http://core.trac.wordpress.org/ticket/13265 )

The only other ‘solution’ (read ‘hack’) that I’ve not seen so far is to de-register the page template metabox and re-register it yourself. But that leaves a nastier taste in my mouth than the jQuery solution.

Hi Tom,
I’ve been looking for something like this for a good while now. Has there been any progress since its release in March?
Thanks,

Tristan

    Hey Tristian – not really. The plugin was more of an experiment and you can tell from the comments that there are certainly some mixed thoughts on it.

    I’m definitely open to additional suggestions or thoughts on it, but know that this particular plugin isn’t a high priority right now. It’s not that I’ve totally abandoned it – it’s just low on the priority list :).

      Hi Tom,
      Ok – are there any other methods for creating page templates out there? Because I am working on a suite of plugins that will include CPTs like Testimonials, Showcases, Team Members and so on, and don’t want to have to create a lengthly handbook that explains how to create CPT page templates…
      Surely there must be something out there?
      Thanks,

      Tristan

        If you’re working on a plugin, then the best bet is likely to programmatically create the files then move them into another directory.

        Another would be to experiment with programmatically setting the template file location by updating the `_wp_page_template` meta data, as well.

        As you can tell from the comments, there’s a lot of mixed opinions on how this can and/or should be done.

        I wish I could offer more advice but that’s really all I’ve got for right now.

Hie Tom,
Could you please let me know when there is a way to do this, other than the “dreaded” injection ofcourse. I’m sure you will get my email form this comment. I have been developing this project/plugin that checks if your websites (if you are a developer that is) are up and takes real time screen shots and returns them to your wordpress website , i wanted a totally different look compared with the theme at work and the only way so far is to manually copy the template files into the theme directory (sucks) . So far this blog post is the only one going to length about this issue and am eager to see how it plays out , thank you.

I am looking for a solution to this too. I guess for now I will have to stick with using a shortcode that brings in my plugin specific “page template”, or adding a Readme to my plugin directory explaining that the site owner needs to copy the page template to the theme directory.

    Yeah – for what it’s worth, I think this is simply a matter of time before a solution is built into core.

    For now, though, we have a limited set of options. There aren’t many ways to achieve what we want (at least as far as I know at this time).

Ok so now that 3.6.1 is out has there been any movement on this issue?

Specifically still I need a (non hacky) way to it’s register the plugin’s template with the drop down menu on the page editor.

    Negative – at least not right now.

    Remember, all of the X.Y.1 releases are generally going to be security updates versus new features. But still, even with 3.6.0 there’s no way to do this (that I’m aware of) other than what’s above.

Nice flow there, Tom. I might use the ‘init’ hook to fire the function of checking and copying template files to theme directory. That because I frequently make many plugin’s templates day by day.

Thanks for the post!

Many thanks for this discussion. You have saved me a lot of time. Seems that I need to hold fire with page template creation in my plugin until the much anticipated get_page_templates() filter is in place.

The plugin helps create landing pages that have a video background e.g http://www.genesisclubpro.com/landing-snow, and I wanted to create different page templates for different page widths (narrow/300px, medium /500px and wide/800px) so the user only had to pick colors and not mess around with CSS too much.

Do you know if there will be any movement on this is WordPress 3.8?

    As far as WordPress 3.8 is concerned, I don’t know.

    I’ll see what I can do in terms of doing a more finalized plugin in the weeks to come, but being as it’s more of a hobby project, it’s a lower priority – for now at least :).

    Thanks for the interest, though, Russell – appreciate it!

WOW…that was an hell of a piece of code. Made my day !
thnx for the effort !

I was looking for this plugin for more than 3 days, Thank you alooooot for this piece of art.
Just one issue, the new templates are loaded in the drop down box ( in edit pages).. but the templates of the themes disappeared :( I see only the 2 new templates made by plugins..
How can I get all the templates to be shown?
Thank you very much.

Cheers

I just stumbled across the roots project recently, and their wrapper seems to do the trick quite nicely. It’s intended for theme development, but a brief read through leads me to believe that it could easily accomplish the task via a plugin as well.

http://roots.io/an-introduction-to-the-roots-theme-wrapper/

Yeah right. Dude. You are an idiot. Your open paragraph of ‘On The “Page Template in Plugin” Discussion’ is simply filled with nonsense. It is irrational on sooo many levels to think that any generic theme should ever accommodate any plugin’s special post type. That is just plain retarded.
There is no blurry line here. If you download a free plugin that lets you put ‘Books’ on your site, and you buy a $55 theme from some dude’s website, there is no way any reasonable, rational person would ever expect that the theme maker was psychic, and KNEW, beyond a shadow of a doubt, that YOU a random end user (out of probably hundreds) have downloaded a random other plugin (out of hundreds of thousands) that provides a random new post type that needs special formatting, called a book.
Your “belief” that “… that themes should be dedicated to providing presentation and layouts for data…” is just plan ignorance to the fact that every person who has a blog needs something different. Not to mention that every person who wants to blog is not a developer who can just whip something together that will work. Your “belief” is misguided, or at the very least, uninformed. It sounds like you have no real world experience dealing with actual websites, other than your’s. For that matter, actual other people who run websites.
The line is only blurry, if you don’t know what you are talking about, or have insufficient experience to know that what you are saying is just plan thoughtless. Granted, about 80% of the work I do is highly customized work, where we start with a basic theme, with basic layouts, and expand on it from there with a child theme, throwing in several thrid party and/or custom plugins to fill out functionality, as is probably any self respecting devleoper’s work. That being said, spreading such and off base comment like “…that themes should be dedicated to providing presentation and layouts for data…” in a world where not everyone is a developer, is just plain irresponsible.
To make this whole post even more painful, you mention “…so long as it’s not a complete abomination of code…,” but then you happily suggest a plugin that breaks every good practice any programmer has ever come up with, and boast that it is the right way. Your article is just falling to shambles now, because the whole thing is about this “totally awesome technique demonstrated in this totally awesome plugin I found/wrote/advocate.” (others are actual quotes, this one is not, for any of you slow readers out there).
Firstly, never, ever, ever, ever assume that a filesystem is writable. On any system that has a developer, sysadmin, or paranoid blogger on it’s team, that has ever had a site of their hacked, had a buddy who’s site got hacked, worked for a company who’s site got hacked, or read about a site being hacked (not even actually hacked, even just hack attempts), would implement at least basic security precautions, one of the easiest and widely accepted techniques being to lock down file permissions. BAM! All of a sudden, your example plugin becomes unusable.
Secondly, never, ever, ever, ever delete a file from anywhere outside your plugin folder, ever, in code, even if you made it with your code. This is probably the worst idea ever thought of, and perpetuated by uninformed people like you because you didn’t think about the consequences. This is exactly the same problem that a certain terrible even calendar plugin (AI1EC) runs into with it’s code, only it is on a much grander level on the idiot scale. They actually delete data when you deactivate their plugin. All of you events, simply gone, unrecoverably gone. This is the same damn problem. What if someone modified the file you made, to include their special logo file, because your file didin’t include a setting for that? Or what if they repurposed it for something else on their site? Or what if they used it as their super secret password storage file? Or worse (I know you are thinking…”how?”)!!! Maybe they already have a file by that name because you didn’t properly uniquify your filename, and you accidentally delete their entire site layout! Who the hell knows what these retards do with your file (or what you are overwriting). There is a moral here. DON’T DELETE THE FILE! geez.
With all of this, at least you did one thing right. You used version control. Thankfully some good developer that you have worked with along the line, has instilled in your base thinking process “Hey we need version control, in case I fuck something up and need to recover it, or Jerry decides to work on the same thing I am.” Thank goodness for that guy!
In conclusion, just because you can type, and you work on your mom’s website on your days off from the machine shop, does not mean you know what you are talking about, or that you should perpetuate your idiosyncrasies to the world, through some blog you threw together with a free theme and a couple free plugins. Especially don’t write about programming or designing, because it is obvious you don’t know anything about either. In fact, just don’t write. Let this domain expire, and forget you ever owned it. That way, there will be one less guy out there spreading misinformation to the wanna be developers, essentially fucking up the whole programming field any more than it already is, with all these losers who can “make a website” but not turn on a computer.

Good day sir!

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>