Including templates inside a plugin
Posted on December 17, 2012
This past week I was working on a project for a client who needed a custom post type to manage events on his site. Normally for a project like this I would build the CPTs and push a couple templates in to the active theme folder. But in this instance, the client was working on a new theme that would be going live in a few weeks. Rather than making the client jump through hoops and move template files around, I wanted to provide the easiest solution possible. That meant, including all the templates as part of the plugin. Thanks to a very handy filter in WordPress, this wasn’t a problem. Here’s how it ended up.
Here’s the makeup of the plugin:
The plugin itself is very standard. One thing I like to do is define the custom post types as separate files to keep the function file clean. I then include the CPTs and the custom metabox library like so:
/** Add custom CPTs and Metaboxes */
require_once( 'cpt-events.php' );
require_once( 'cpt-locations.php' );
require_once( 'metabox/init.php' );
I store the stylesheet in a separate folder for cleanliness as well and encode it like this:
/** Enqueue CSS */
add_action( 'wp_enqueue_scripts', 'prefix_add_my_stylesheet' );
function prefix_add_my_stylesheet() {
wp_register_style( 'cpt-style', plugins_url( 'css/style.css', __FILE__) );
wp_enqueue_style( 'cpt-style' );
}
And now the real meat of it. You can see the single-events.php and archive-events.php that make up the two template files I want to use on the front end. What I’m going to do is create a function that tells WordPress to use my templates for the archive and single pages for the event CPT. That code looks like this:
// force use of templates from plugin folder
function cpte_force_template( $template )
{
if( is_archive( 'events' ) ) {
$template = WP_PLUGIN_DIR .'/'. plugin_basename( dirname(__FILE__) ) .'/archive-events.php';
}
if( is_singular( 'events' ) ) {
$template = WP_PLUGIN_DIR .'/'. plugin_basename( dirname(__FILE__) ) .'/single-events.php';
}
return $template;
}
add_filter( 'template_include', 'cpte_force_template' );
As you can see, I’ve set up a filter for template_include. I pass in the $template variable and check to see if the page is either an archive or singular event. If so, I override the default template location with the full path and file name of the file inside my plugin folder.
The end result is a fully encapsulated plugin that takes care of the functionality, templates and stylesheet formatting the client requested all in one easy to manage package. Simply install the plugin and activate it and you’re ready to go!
Thanks John, that was just what I was looking for! I also added is_page('page-name') for my main plugin page, with a note to create a blank page with the same slug.
Thanks a lot. Exactly what I was searching for.
Hello, This is exactly what I am looking to achieve! Thank you for the tutorial. I have a site-plugin to centralize most of the theme customization and want to override the default footer.php template with a customfooter.php (removes the Proudly Powered by WordPress) stored inside the /plugins directory structure. I found your post and tried some. Obviously, as a newb, I am making errors. Could you please advise how to? Here's what I have: add_filter( 'theme_page_templates', 'force_customization', 101 ); function force_customization( $newtemplate ) { if ( is_singular( 'footer' ) ) { $newtemplate = plugin_dir_path( FILE ) . 'customization/customfooter.php'; } return $newtemplate; }
"add_filter( 'theme_page_templates', 'force_customization', 101 ); function force_customization( $newtemplate ) { if ( is_singular( 'footer' ) ) { $newtemplate = plugin_dir_path( FILE ) . 'customization/customfooter.php'; } return $newtemplate; }"
Assuming that the rest is correct if ( is_singular( 'footer' )) doesn't make sense. 'footer' typically is a template part, not a template. That's always going to be false, you should test that though.
Thank you for your thoughts. Yes, I tested and it doesn't work :) I'm trying to reduce my administrative overheads of managing the site by centralizing all customization. Frankly, I'm a newb to coding and WP and the terms are confusing. Some sites refer to PHP files as templates while others refer to the entire theme as a template. When I saw your post, I saw hope :) This is exactly what I'm after. Could you please suggest an alternate method to replace the footer.php from my plugin? Any inputs / suggestions are welcome. Kind regards Abhijeet
The wider web community will sometimes use the term "template" to refer to the entire theme because once upon a time people would buy a static html template design and fill in the blanks to make a site. In more modern parlance a WordPress theme is made up of one or more templates, and each of those may include partial templates or template parts. In short "template" is pretty generic and covers all sorts of things. if (is_singular('slug')) checks if the template is named slug (ie. single, page, page-about). It wouldn't make any sense to name that footer. What you want to change is the get_footer() call. See https://developer.wordpress.org/reference/functions/get_footer/#user-contributed-notes Obviously, this is getting a bit beyond the original post and what I can clarify in a comment. Good luck though I'm sure you'll figure it out!
Thank you Jon. Really appreciate the direction here. I will also consult the theme folks whether they provide a ready hook to do this from inside a plugin. Kind regards Abhijeet
When creating plugins I've often opt to use shortcodes for content insertion, as we developers usually have no idea how a theme/template, outside of our control, will behave. The idea of inserting a template via the plugin seems like it would work on the surface, but with so many different types of themes in the wild, how can we prevent out-of-the-box breakage of the users theme look and feel? Is there a consistent want to affect only the themes/templates "content" area for archive and single pages (e.g. for custom post types)?
Sure, you can restrict the affect using normal WordPress template tags like is_single() and is_archive(), or more likely in this case is_page_template() or is_post_type_archive(), etc...
Many thanks! Works great! - Brian
I love you man..! You save my day.. After lots of hunt u became my saviour.