Come posso caricare un template di pagina da un plugin?
Vorrei aggiungere template di pagina a un tema direttamente dal plugin. L'idea è che il template dovrebbe apparire nel menu a tendina sotto Attributi Pagina, e tutto il codice dovrebbe essere contenuto nel plugin.
Avete suggerimenti su come realizzarlo?

Puoi utilizzare il filtro theme_page_templates
per aggiungere template alla lista a discesa dei template di pagina in questo modo:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'Il mio Template';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
Ora WordPress cercherà il file my-custom-template.php
nella directory del tema, quindi dovrai reindirizzarlo alla directory del tuo plugin utilizzando il filtro page_template
in questo modo:
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');
Leggi di più su questo argomento qui: Aggiungere un template di pagina personalizzato programmaticamente

dalla versione 4.7 di WordPress, il codice sopra non funzionerà. modifica questa riga da '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 ))

Questa è una combinazione della risposta sopra e dei commenti sopra che alla fine hanno funzionato per me.
La funzione per aggiungere il plugin alla lista dei template disponibili:
function wpse255804_add_page_template ($templates) {
$templates['my-custom-template.php'] = 'Il mio Template';
return $templates;
}
add_filter ('theme_page_templates', 'wpse255804_add_page_template');
La funzione per puntare il template alla directory appropriata all'interno 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');

Grazie per l'aiuto. Ho modificato un po' il codice per farlo funzionare con la versione attuale di WordPress. Ho anche cambiato il codice per supportare più di un template personalizzato.
Scommetto che esiste un modo migliore per farlo, ma ha funzionato per me.
/**
* Carica Template con Plugin
*/
function yourname_add_page_template ($templates) {
$templates['page-one.php'] = 'titolo qui Uno';
$templates['page-two.php'] = 'titolo qui Due';
$templates['page-three.php'] = 'titolo qui Tre';
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');

Dal codice:
<?php
$templates = get_page_templates();
foreach ( $templates as $template_name => $template_filename ) {
echo "$template_name ($template_filename)<br />";
}
?>
Puoi quindi utilizzare i template correnti e aggiungerli in modo programmatico a qualsiasi cosa desideri.

Il seguente frammento di codice è ben progettato: cercherà un template nel plugin e, se non lo trova, proverà a recuperarlo dal 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 );
// Questo ci restituirà archive.php
$new_template = end( $provided_template_array );
// Definisce i template single e archive per il 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;
}
Fonte: https://www.ibenic.com/include-or-override-wordpress-templates/

Ecco un aggiornamento per il 2022: Il codice qui sotto aggiungerà un template alla lista dei template di pagina e lo registrerà all'interno dei file del tuo plugin
// ------------registra il template personalizzato nella lista dei template di pagina------------
function register_custom_template_list ($templates) {
// ------------associa il nome visualizzato del template al nome del file------------
$templates['my-template.php'] = 'Nome del Mio Template';
// ------------restituisce la lista dei template di pagina con la nuova aggiunta------------
return $templates;
}
// ------------aggancia il template personalizzato alla lista dei template di pagina------------
add_filter('theme_page_templates', 'register_custom_template_list');
// ------------registra il file del template per la pagina------------
function render_custom_template_archive ($template) {
// ------------ottieni gli attributi della pagina attualmente modificata------------
$post = get_post();
$page_template = get_post_meta( $post->ID, '_wp_page_template', true );
// ------------verifica se il template selezionato è quello personalizzato------------
if (basename ($page_template) == 'my-template.php'){
// ------------associa il file del template personalizzato alla pagina------------
$template = dirname(__DIR__).'/percorso_del_template/my-template.php';
// ------------restituisce il contenuto del template personalizzato------------
return $template;
} else {
// ------------restituisce il template selezionato se non è quello personalizzato------------
return $template;
}
}
// ------------aggancia il template personalizzato al file------------
add_filter('page_template', 'render_custom_template_archive');

@Rup Ho commentato il codice per rendere più chiara la differenza. La differenza principale sta nell'ultima parte di "render_custom_template_archive". L'istruzione else garantisce che anche altri template di pagina possano essere caricati. La risposta accettata/la soluzione di TKEz ha rotto il mio sito WP e ha causato il rendering del mio template personalizzato su tutte le pagine. Ho dovuto resettare completamente il sito per farlo funzionare (per fortuna era un sito di test).

Entrambe dovrebbero funzionare bene così come sono, a meno che non si aggiungano parentesi graffe extra. Entrambe le funzioni terminano con return $template che verrà eseguito sia che la condizione sia vera o falsa.

Ora che WordPress supporta l'uso di quelli che tradizionalmente venivano chiamati Page Template anche con altri tipi di post, potrebbe essere utile un esempio aggiornato che funzioni sia per i post e i custom post type che per le pagine.
/*
Plugin Name: Example Plugin Templates
Plugin URI:
Description: Carica template di pagine (o tipi di post) da 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' => 'Plugin Template 1'
,'template-name-2.php' => 'Plugin Template 2'
,'template-name-3.php' => 'Plugin Template 3'
];
public function __construct() {
// Hook tardivo per dare tempo a plugin/temi di registrare i post type
add_action( 'init', [$this, 'on_init'], 5000 );
}
public function on_init() {
// Filtri hook, perché 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 );
// Imposta i post types
$this->types = get_post_types( $this->args );
// Non usiamo page template con gli allegati
unset( $this->types['attachment'] );
// Aggiunge file custom alla lista dei template
add_filter( 'theme_templates', [$this,'add_plugin_templates'], 1000, 4 );
// Se la pagina è uno dei tipi
if( isset( $this->types['page'] ) )
add_filter( 'page_template', [$this,'set_plugin_page_template'], 1000, 3 );
// E gestisce gli altri post type
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;
}
// Funzione semplice per debug/controllo valori
private function pre( $s ) {
printf( '<pre>%s</pre>', print_r( $s, true ) );
}
}
new Plugin_Templates;
Ho cercato di non essere troppo astratto e di mantenere la logica abbastanza semplice, per qualsiasi problema, aggiungete un commento.

<?php load_template( $_template_file, $require_once ) ?>
Questo viene dai primi risultati di ricerca su Google per "caricare template da plugin". Per favore, fai uno sforzo per trovare le risposte da solo prima di chiedere qui.

Se non vuoi che il tema o il tema child possa sovrascrivere il template del plugin, allora usa semplicemente require($template)
