If you’ve ever worked with WooCommerce theming, you’ve probably had to copy some of their templates files to your own theme in order to override the HTML. It’s a great system that allows front enders the ability to change the output to match designs. In this article, I’ll walk you through how to do just that — easily add WordPress plugin template files.
Let’s get started!
In this tutorial, we’ll create a templates
folder within the plugin where we’ll add our… you guessed it, templates. Here we’ll place the templates that can be overridden in themes. These templates will be loaded via a custom plugin template function that will be called in place of WordPress’ get_template_part
function.
Step 1: Locating the right template
In order for this to work, WordPress needs to be able to find the correct template file to load — the plugin or theme template. With the code below, WordPress will first look in the theme’s templates
folder, if not found then will search in the main theme’s folder and then if still not found will fallback to the plugin’s templates
folder.
<?php
/**
* Locate template.
*
* Locate the called template.
* Search Order:
* 1. /themes/theme/templates/$template_name
* 2. /themes/theme/$template_name
* 3. /plugins/plugin/templates/$template_name.
*
* @since 1.0.0
*
* @param string $template_name Template to load.
* @param string $string $template_path Path to templates.
* @param string $default_path Default path to template files.
* @return string Path to the template file.
*/
function PLUGIN_locate_template( $template_name, $template_path = '', $default_path = '' ) {
// Set variable to search in the templates folder of theme.
if ( ! $template_path ) :
$template_path = 'templates/';
endif;
// Set default plugin templates path.
if ( ! $default_path ) :
$default_path = plugin_dir_path( __FILE__ ) . 'templates/'; // Path to the template folder
endif;
// Search template file in theme folder.
$template = locate_template( array(
$template_path . $template_name,
$template_name
) );
// Get plugins template file.
if ( ! $template ) :
$template = $default_path . $template_name;
endif;
return apply_filters( 'PLUGIN_locate_template', $template, $template_name, $template_path, $default_path );
}
Step 2: Loading the template file
Now that WordPress can find the right template, we need a function to load it. This is what will be used in place of get_template_part
.
<?php
/**
* Get template.
*
* Search for the template and include the file.
*
* @since 1.0.0
*
* @see PLUGIN_locate_template()
*
* @param string $template_name Template to load.
* @param array $args Args passed for the template file.
* @param string $string $template_path Path to templates.
* @param string $default_path Default path to template files.
*/
function PLUGIN_get_template( $template_name, $args = array(), $tempate_path = '', $default_path = '' ) {
if ( is_array( $args ) && isset( $args ) ) :
extract( $args );
endif;
$template_file = contests_locate_template( $template_name, $tempate_path, $default_path );
if ( ! file_exists( $template_file ) ) :
_doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $template_file ), '1.0.0' );
return;
endif;
include $template_file;
}
Step 3: Override the WordPress template file
Lastly, we’ll override the default WordPress template file with the code below.
<?php
/**
* Template loader.
*
* The template loader will check if WP is loading a template
* for a specific Post Type and will try to load the template
* from out 'templates' directory.
*
* @since 1.0.0
*
* @param string $template Template file that is being loaded.
* @return string Template file that should be loaded.
*/
function PLUGIN_template_loader( $template ) {
$find = array();
$file = '';
if( is_singular() ):
$file = 'single-plugin.php';
elseif( is_tax() ):
$file = 'archive-plugin.php';
endif;
if ( file_exists( PLUGIN_locate_template( $file ) ) ) :
$template = PLUGIN_locate_template( $file );
endif;
return $template;
}
add_filter( 'template_include', 'PLUGIN_template_loader' );
Putting It All Together
<?php
/**
* Locate template.
*
* Locate the called template.
* Search Order:
* 1. /themes/theme/templates/$template_name
* 2. /themes/theme/$template_name
* 3. /plugins/plugin/templates/$template_name.
*
* @since 1.0.0
*
* @param string $template_name Template to load.
* @param string $string $template_path Path to templates.
* @param string $default_path Default path to template files.
* @return string Path to the template file.
*/
function PLUGIN_locate_template( $template_name, $template_path = '', $default_path = '' ) {
// Set variable to search in the templates folder of theme.
if ( ! $template_path ) :
$template_path = 'templates/';
endif;
// Set default plugin templates path.
if ( ! $default_path ) :
$default_path = plugin_dir_path( __FILE__ ) . 'templates/'; // Path to the template folder
endif;
// Search template file in theme folder.
$template = locate_template( array(
$template_path . $template_name,
$template_name
) );
// Get plugins template file.
if ( ! $template ) :
$template = $default_path . $template_name;
endif;
return apply_filters( 'PLUGIN_locate_template', $template, $template_name, $template_path, $default_path );
}
/**
* Get template.
*
* Search for the template and include the file.
*
* @since 1.0.0
*
* @see PLUGIN_locate_template()
*
* @param string $template_name Template to load.
* @param array $args Args passed for the template file.
* @param string $string $template_path Path to templates.
* @param string $default_path Default path to template files.
*/
function PLUGIN_get_template( $template_name, $args = array(), $tempate_path = '', $default_path = '' ) {
if ( is_array( $args ) && isset( $args ) ) :
extract( $args );
endif;
$template_file = PLUGIN_locate_template( $template_name, $tempate_path, $default_path );
if ( ! file_exists( $template_file ) ) :
_doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $template_file ), '1.0.0' );
return;
endif;
include $template_file;
}
/**
* Template loader.
*
* The template loader will check if WP is loading a template
* for a specific Post Type and will try to load the template
* from out 'templates' directory.
*
* @since 1.0.0
*
* @param string $template Template file that is being loaded.
* @return string Template file that should be loaded.
*/
function PLUGIN_template_loader( $template ) {
$find = array();
$file = '';
if( is_singular() ):
$file = 'single-plugin.php';
elseif( is_tax() ):
$file = 'archive-plugin.php';
endif;
if ( file_exists( PLUGIN_locate_template( $file ) ) ) :
$template = PLUGIN_locate_template( $file );
endif;
return $template;
}
add_filter( 'template_include', 'PLUGIN_template_loader' );
6 comments on “Add WordPress Plugin Template Files”.
# Jul 1, 2018
Здравствуйте! Implement the following template tags to add WordPress-generated class attributes to body, post, and comment elements. For post classes, apply only to elements within The Loop .
# Jun 7, 2018
Thanks for this post as it helps me to get started.
Unfortunately there are some problems with it.
– What @john said (guard for Post Type).
– What is this function call to
contests_locate_template
?– The function
PLUGIN_get_template
is never called!– What is apply_filters( ‘PLUGIN_locate_template’,…) for? As there are no filters elsewhere defined I don’t get it.
Cheers!
# Jun 2, 2020
To answer your questions Clemens, because I know you’re still just dying to know 😉
– contests_locate_template should be PLUGIN_locate_template. It’s just a little typo.
– Replace PLUGIN with your plugin slug or whatever.
– PLUGIN_get_template would be called by your plugin, it doesn’t need to be called in this code!
– Filters could be accessed by third-party and end users.
# Apr 5, 2018
Thanks for this example, great way to get started and does exactly what I was looking for.
Shoutout to John’s comment that suggests adding a check, this is quite necessary since any other page that is NOT a custom post type will give an error.
# Aug 16, 2017
Hi, I was looking for how to do this, great, thank you 🙂 But to understand, can we have an example of usage? Thank you
# Aug 13, 2017
Of all the methods and techniques I have tried, and I have tried several, this one worked! To make it specific to only load my modified templates for my plugin, I added a check in the
"function PLUGIN_template_loader( $template )…" Just before testing for the template to load like this:
function PLUGIN_template_loader( $template ) {
$find = array();
$file = ”;
/ Is this concerning the "Basic Plugin" cpt? /
if (get_post_type() !== "my-basic-test-plugin") { // (or whatever plugin/post type you want to create of course)
return $template;
}
if( is_singular() ):
$file = ‘single-basic-plugin.php’;
elseif( is_tax() ):
$file = ‘archive-basic-plugin.php’;
endif;
Works like a charm!
Sincere THANK YOU!!
All comments posted on 'Add WordPress Plugin Template Files' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.
You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.
Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.