I want to add page templates to a theme directly from the plugin. The idea is that the template would show up in the dropdown under Page Attributes, and all the code would need to be in the plugin.
Any tips on how to achieve that ?
You can use the theme_page_templates
filter to add templates to the dropdown list of page templates like this:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'My Template';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
Now WP will be searching for my-custom-template.php
in the theme directory, so you will have to redirect that to your plugin directory by using the page_template
filter like this:
function wpse255804_redirect_page_template ($template) {
if ('my-custom-template.php' == basename ($template))
$template = WP_PLUGIN_DIR . '/mypluginname/my-custom-template.php';
return $template;
}
add_filter ('page_template', 'wpse255804_redirect_page_template');
Read more about this here: Add custom template page programmatically
This is a combination of the above answer and the above comments which ended up working for me.
The function to add the plugin to the list of available templates:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'My Template';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
The function to point the template to the appropriate directory within the plugin:
function wpse255804_redirect_page_template ($template) {
$post = get_post();
$page_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ('my-custom-template.php' == basename ($page_template))
$template = WP_PLUGIN_DIR . '/mypluginname/my-custom-template.php';
return $template;
}
add_filter ('page_template', 'wpse255804_redirect_page_template');
Thanks for the help. I changed the code a little to work with the current WordPress version. Also changed it to support more than one custom template.
I bet there is a better way of doing this but it worked for me.
/**
* Load Template with Plugin
*/
function yourname_add_page_template ($templates) {
$templates['page-one.php'] = 'title here One';
$templates['page-two.php'] = 'title here Two';
$templates['page-three.php'] = 'title here Three';
return $templates;
}
add_filter ('theme_page_templates', 'yourname_add_page_template');
function yourname_redirect_page_template ($template) {
$post = get_post();
$page_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ('page-one.php' == basename ($page_template)) {
$template = WP_PLUGIN_DIR . '/pluginname/templates/page-one.php';
return $template;
}
elseif ('page-two.php' == basename ($page_template)) {
$template = WP_PLUGIN_DIR . '/pluginname/templates/page-two.php';
return $template;
}
elseif ('page-three.php' == basename ($page_template)) {
$template = WP_PLUGIN_DIR . '/pluginname/templates/page-three.php';
return $template;
}
}
add_filter ('page_template', 'yourname_redirect_page_template');
From the codex:
<?php
$templates = get_page_templates();
foreach ( $templates as $template_name => $template_filename ) {
echo "$template_name ($template_filename)<br />";
}
?>
You get then use the current templates and programmatically add them to whatever you wish.
The below code snippet is very well thought out, it will try to look for a template in the plugin and if it can't find it there it will try to get it from the theme.
define( 'MY_PLUGIN_DIR', plugin_dir_path( __FILE __ ) );
define( 'MY_PLUGIN_TEMPLATE_DIR', MY_PLUGIN_DIR . '/templates/' );
add_filter( 'template_include', 'ibenic_include_from_plugin', 99 );
function ibenic_include_from_plugin( $template ) {
$new_template = '';
$provided_template_array = explode( '/', $template );
// This will give us archive.php
$new_template = end( $provided_template_array );
// Define single and archive template for custom post type 'portfolio'
if( is_singular('portfolio') ) {
$new_template = 'single-portfolio.php';
}
if( is_post_type_archive( 'portfolio' ) ) {
$new_template = 'archive-portfolio.php';
}
$plugin_template = MY_PLUGIN_TEMPLATE_DIR . $new_template;
if( file_exists( $plugin_template ) ) {
return $plugin_template;
}
return $template;
}
Source: https://www.ibenic.com/include-or-override-wordpress-templates/
Now that WordPress supports using what was traditionally referred to as Page Templates with other post types, it seems like an updated example that works for posts and custom post types as well as pages might be helpful.
/*
Plugin Name: Example Plugin Templates
Plugin URI:
Description: Load page(or post type) templates from a plugin
Version: 0.1
Requires at least: 6.0
Requires PHP: 7
Author: t31os
Author URI:
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
namespace t31os\Plugin;
if( !defined('ABSPATH') )
exit;
class Plugin_Templates {
private $types;
private $args;
private $folder;
private $templates = [
'template-name-1.php' => 'Plugin Template 1'
,'template-name-2.php' => 'Plugin Template 2'
,'template-name-3.php' => 'Plugin Template 3'
];
public function __construct() {
// Hook late so plugins/themes have time to register post types
add_action( 'init', [$this, 'on_init'], 5000 );
}
public function on_init() {
// Filter hooks, because why not!
$this->args = apply_filters( 'my_plugin_template_type_args', [ 'public' => true ] );
$this->folder = apply_filters( 'my_plugin_template_directory', __DIR__ . '/templates/' );
$this->templates = apply_filters( 'my_plugin_template_file_list', $this->templates );
// Set the post types
$this->types = get_post_types( $this->args );
// We don't use page templates with attachments
unset( $this->types['attachment'] );
// Add custom files to template list
add_filter( 'theme_templates', [$this,'add_plugin_templates'], 1000, 4 );
// If page is one of the types
if( isset( $this->types['page'] ) )
add_filter( 'page_template', [$this,'set_plugin_page_template'], 1000, 3 );
// And deal with other post types
add_filter( 'single_template', [$this,'set_plugin_type_template'], 1000, 3 );
}
public function add_plugin_templates( $post_templates, $obj, $post, $post_type ) {
if( !isset( $this->types[$post_type] ) )
return $post_templates;
foreach( $this->templates as $file => $name )
$post_templates[$file] = $name;
return $post_templates;
}
private function is_plugin_template( $file ) {
return (bool) isset( $this->templates[$file] ) && file_exists( $this->folder . $file );
}
public function set_plugin_page_template( $template, $type, $templates ) {
if( !isset( $templates[0] ) )
return $template;
if( $this->is_plugin_template( $templates[0] ) )
return $this->folder . $templates[0];
return $template;
}
public function set_plugin_type_template( $template, $type, $templates ) {
if( !isset( $templates[0] ) || 'single' !== $type )
return $template;
if( $this->is_plugin_template( $templates[0] ) )
return $this->folder . $templates[0];
return $template;
}
// Simple function for debugging / checking values
private function pre( $s ) {
printf( '<pre>%s</pre>', print_r( $s, true ) );
}
}
new Plugin_Templates;
I tried not to be too abstract and keep the logic fairly simple, any problems, add a comment.
Here's an update for 2022: Below this code will add a template to the page template list and register it within your plugin files
// ------------register page template to page template lists------------
function register_custom_template_list ($templates) {
// ------------register template display name to file name------------
$templates['my-template.php'] = 'My Template Name';
// ------------return page template list with new addition------------
return $templates;
}
// ------------hook page template to page template lists------------
add_filter('theme_page_templates', 'register_custom_template_list');
// ------------register page template to file------------
function render_custom_template_archive ($template) {
// ------------get currently edited page attributes------------
$post = get_post();
$page_template = get_post_meta( $post->ID, '_wp_page_template', true );
// ------------check if selected template is for custom template------------
if (basename ($page_template) == 'my-template.php'){
// ------------register page template file to page------------
$template = dirname(__DIR__).'/path_to/my-template.php';
// ------------render custom template content template------------
return $template;
} else {
// ------------return selected template if custom template is not selected------------
return $template;
}
}
// ------------hook page template to file------------
add_filter('page_template', 'render_custom_template_archive');
<?php load_template( $_template_file, $require_once ) ?>
That is from the very 1st google search results for "load template from plugin". Please make an effort to find the answers yourself before asking here.
require($template)