HowTo: WordPress Plugin Supplied Templates for Custom Post Types

While prototyping a WordPress plugin I’m writing, I experimented with supplying default templates to display pages related to a custom post type. This is accomplished using the template_redirect action API.  If the following technique is not used, any special templates a plugin provides would need to be copied to the active theme, making plugin installation more complex than necessary.

The first step in building the template_redirect action is to determine if the page being displayed is either a single page or archive of the custom post type. WordPress supplies the functions is_singular() and is_post_type_archive() for this purpose. If it’s a page that does not have a plugin supplied template, the function should return allowing WordPress core to select the correct template to use.

if (is_singular($my_post_type)) {
  $template_name = 'single-';
} elseif (is_post_type_archive($my_post_type)) {
  $template_name = 'archive-';
} else {
  return;
}

Next, I build the full name for the template file that will be used and attempt to locate one supplied by the active theme. The WordPress function locate_template() will return the path to a matching template if one is present.

$template_name .= get_post_type($post) . '.php';
// Look for theme provided template
$template = locate_template(array($template_name), true);

Finally, if the theme does not supply a template, the plugin supplied default template is used. When the template_redirect action does use an alternate template, it is expected to exit and no further processing should be done by WordPress core.

if (empty($template)) {
  include(WP_PLUGIN_DIR . '/my-plugin-dir/template/' . $template_name);
}
exit();

Putting this all together, here’s the entire code snippet:

function my_template_redirect()
{
  global $post;
  global $my_post_type;
  if (is_singular($my_post_type)) {
    $template_name = 'single-';
  } elseif (is_post_type_archive($my_post_type)) {
    $template_name = 'archive-';
  } else {
    return;
  }
  $template_name .= get_post_type($post) . '.php';
  // Look for available templates
  $template = locate_template(array($template_name), true);
  if (empty($template)) {
    include(WP_PLUGIN_DIR . '/my-plugin-dir/template/' . $template_name);
  }
  exit();
}
add_action('template_redirect', 'my_template_redirect');

Posted by Ken

Toastmaster, Woodworker, Craft Beer Enthusiast and dutiful supporter of three demanding house cats. I'm also an experienced Software Engineering Manager with a demonstrated history of working in the Information Technology and Services industry. Skilled in Operating System Development, Unix, SPARC Servers, Wordpress and PHP.

Leave a Reply

Your email address will not be published. Required fields are marked *