¿Cómo puedo cargar una plantilla de página desde un plugin?
Quiero agregar plantillas de página a un tema directamente desde el plugin. La idea es que la plantilla aparezca en el menú desplegable dentro de Atributos de página, y todo el código necesita estar en el plugin.
¿Algún consejo sobre cómo lograr esto?

Puedes usar el filtro theme_page_templates
para agregar plantillas al menú desplegable de plantillas de página de esta manera:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'Mi Plantilla';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
Ahora WordPress buscará el archivo my-custom-template.php
en el directorio del tema, por lo que tendrás que redirigirlo al directorio de tu plugin usando el filtro page_template
así:
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');
Lee más sobre esto aquí: Agregar plantilla de página personalizada programáticamente

Desde la versión 4.7 de WordPress, el código anterior no funcionará. Cambia esta línea de 'if ('my-custom-template.php' == basename ($template))' a $post = get_post(); $page_template = get_post_meta( $post->ID, '_wp_page_template', true ); if ('my-custom-template.php' == basename ($page_template ))

Esta es una combinación de la respuesta anterior y los comentarios anteriores que terminaron funcionando para mí.
La función para agregar el plugin a la lista de plantillas disponibles:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'Mi Plantilla';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
La función para dirigir la plantilla al directorio apropiado dentro del 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');

Gracias por la ayuda. Modifiqué un poco el código para que funcione con la versión actual de WordPress. También lo cambié para que admita más de una plantilla personalizada.
Apuesto a que hay una mejor manera de hacer esto, pero funcionó para mí.
/**
* Cargar plantilla con el Plugin
*/
function yourname_add_page_template ($templates) {
$templates['page-one.php'] = 'título aquí Uno';
$templates['page-two.php'] = 'título aquí Dos';
$templates['page-three.php'] = 'título aquí Tres';
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');

Del Codex:
<?php
$templates = get_page_templates();
foreach ( $templates as $template_name => $template_filename ) {
echo "$template_name ($template_filename)<br />";
}
?>
Luego puedes utilizar las plantillas actuales y agregarlas programáticamente a lo que desees.

El siguiente fragmento de código está muy bien pensado, intentará buscar una plantilla en el plugin y si no la encuentra allí, intentará obtenerla del tema.
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 );
// Esto nos dará archive.php
$new_template = end( $provided_template_array );
// Definir plantilla single y archive para el tipo de contenido personalizado '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;
}
Fuente: https://www.ibenic.com/include-or-override-wordpress-templates/

Aquí hay una actualización para 2022: A continuación, este código agregará una plantilla a la lista de plantillas de página y la registrará dentro de tus archivos de plugin
// ------------registrar plantilla de página en la lista de plantillas------------
function register_custom_template_list ($templates) {
// ------------registrar nombre de visualización de la plantilla al nombre del archivo------------
$templates['my-template.php'] = 'Mi Nombre de Plantilla';
// ------------devolver lista de plantillas de página con la nueva adición------------
return $templates;
}
// ------------conectar plantilla de página a la lista de plantillas------------
add_filter('theme_page_templates', 'register_custom_template_list');
// ------------registrar plantilla de página en el archivo------------
function render_custom_template_archive ($template) {
// ------------obtener atributos de la página actualmente editada------------
$post = get_post();
$page_template = get_post_meta( $post->ID, '_wp_page_template', true );
// ------------verificar si la plantilla seleccionada es para la plantilla personalizada------------
if (basename ($page_template) == 'my-template.php'){
// ------------registrar archivo de plantilla de página en la página------------
$template = dirname(__DIR__).'/path_to/my-template.php';
// ------------renderizar contenido de la plantilla personalizada------------
return $template;
} else {
// ------------devolver plantilla seleccionada si no se eligió la plantilla personalizada------------
return $template;
}
}
// ------------conectar plantilla de página al archivo------------
add_filter('page_template', 'render_custom_template_archive');

@Rup He comentado el código para hacer la diferencia más clara. La principal diferencia está en la última parte de "render_custom_template_archive". La sentencia else asegura que otras plantillas de página también puedan cargarse. La respuesta aceptada/de TKEz rompió mi sitio WP y hacía que todas las páginas mostraran mi plantilla personalizada. Tuve que reiniciar completamente el sitio para que funcionara (afortunadamente era un sitio de pruebas).

Ambas deberían funcionar bien tal cual, a menos que añadas llaves adicionales. Ambas funciones terminan con return $template que se ejecutará sin importar si la condición es verdadera o no.

Ahora que WordPress admite el uso de lo que tradicionalmente se conocía como Plantillas de Página con otros tipos de contenido, parece que un ejemplo actualizado que funcione para entradas, tipos de contenido personalizados y páginas podría ser útil.
/*
Plugin Name: Ejemplo de Plantillas para Plugin
Plugin URI:
Description: Carga plantillas de página (o tipo de contenido) desde un 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' => 'Plantilla de Plugin 1'
,'template-name-2.php' => 'Plantilla de Plugin 2'
,'template-name-3.php' => 'Plantilla de Plugin 3'
];
public function __construct() {
// Se ejecuta tarde para dar tiempo a que plugins/theme registren tipos de contenido
add_action( 'init', [$this, 'on_init'], 5000 );
}
public function on_init() {
// Filtros, ¡por qué no!
$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 );
// Establecer los tipos de contenido
$this->types = get_post_types( $this->args );
// No usamos plantillas con adjuntos
unset( $this->types['attachment'] );
// Añadir archivos personalizados a la lista de plantillas
add_filter( 'theme_templates', [$this,'add_plugin_templates'], 1000, 4 );
// Si la página es uno de los tipos
if( isset( $this->types['page'] ) )
add_filter( 'page_template', [$this,'set_plugin_page_template'], 1000, 3 );
// Y manejar otros tipos de contenido
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;
}
// Función simple para depuración / verificación de valores
private function pre( $s ) {
printf( '<pre>%s</pre>', print_r( $s, true ) );
}
}
new Plugin_Templates;
Intenté no ser demasiado abstracto y mantener la lógica bastante simple, cualquier problema, añade un comentario.

<?php load_template( $_template_file, $require_once ) ?>
Eso proviene de los primeros resultados de búsqueda en Google para "cargar plantilla desde plugin". Por favor, haz un esfuerzo por encontrar las respuestas tú mismo antes de preguntar aquí.

Si no deseas que el tema o el tema hijo puedan sobrescribir la plantilla del plugin, simplemente usa require($template)
