Template per Custom Post Type dalla Cartella dei Plugin?
Vorrei offrire il mio custom post type come Plugin, in modo che le persone possano utilizzarlo senza dover modificare la cartella del loro tema. Tuttavia, i template dei custom post type -- come single-movies.php -- risiedono nella cartella del tema. Esiste un modo per far sì che WordPress cerchi il file single-movies.php nella cartella del plugin? Agganciando una funzione alla Gerarchia dei Template? Oppure usando get_template_directory(); ?

Puoi utilizzare il filtro single_template
.
/* Filtra il single_template con la nostra funzione personalizzata */
add_filter('single_template', 'my_custom_template');
function my_custom_template($single) {
global $post;
/* Controlla il template single in base al post type */
if ( $post->post_type == 'NOME POST TYPE' ) {
if ( file_exists( PERCORSO_PLUGIN . '/Custom_File.php' ) ) {
return PERCORSO_PLUGIN . '/Custom_File.php';
}
}
return $single;
}

È una risposta fantastica. Potresti condividere dove posso trovare tutti gli hook disponibili per i template come single_template?

@gowri Il filtro viene chiamato dalla funzione get_query_template()
. È un hook variabile, quindi la prima parte {$type}_template
cambia a seconda del parametro passato a quella funzione. Guarda wp-includes/template.php per alcuni esempi comuni

Questo tutorial copre l'hook single_template con una buona spiegazione. Una volta compresi gli hook, il commento di @shea suggerisce un approccio più semplice rispetto alla risposta di @Bainternet, utilizzando add_filter( 'single-movies_template', 'my_custom_template' );
come nel tutorial linkato. (Questa domanda è chiusa a nuove risposte, quindi non posso aggiungerla separatamente.)

Potresti sostituire PLUGIN_PATH
con plugin_dir_path( __FILE__ )
e poi rimuovere la prima barra dal nome del tuo file. Il percorso completo sarebbe qualcosa di simile: return plugin_dir_path( __FILE__ ) . 'Custom_File.php';

PLUGIN_PATH ha generato un errore, ecco un ottimo post che mostra come fare e che ha funzionato subito per me: https://wpsites.net/free-tutorials/load-single-template-from-plugin-for-different-post-types/

Risposta aggiornata
Versione più pulita e concisa.
function load_movie_template( $template ) {
global $post;
if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
/*
* Questo è un post di tipo 'movie'
* E il template 'single movie' non viene trovato
* nella directory del tema o child theme, quindi lo carichiamo
* dalla directory del nostro plugin.
*/
return plugin_dir_path( __FILE__ ) . 'single-movie.php';
}
return $template;
}
add_filter( 'single_template', 'load_movie_template' );
Vecchia risposta
Aggiunto un controllo per un template specifico del custom post type nella cartella del tema alla risposta di @Brainternet.
function load_cpt_template($template) {
global $post;
// È un post di tipo "my-custom-post-type"?
if ($post->post_type == "my-custom-post-type"){
//Percorso del tuo plugin
$plugin_path = plugin_dir_path( __FILE__ );
// Nome del template single per il custom post type
$template_name = 'single-my-custom-post-type.php';
// Esiste un template single specifico per il mio custom post type nella cartella del tema? O non esiste nemmeno nel mio plugin?
if($template === get_stylesheet_directory() . '/' . $template_name
|| !file_exists($plugin_path . $template_name)) {
//Allora restituisci "single.php" o "single-my-custom-post-type.php" dalla directory del tema.
return $template;
}
// Altrimenti, restituisci il template del custom post type dal mio plugin.
return $plugin_path . $template_name;
}
//Questo non è il mio custom post type, non fare nulla con $template
return $template;
}
add_filter('single_template', 'load_cpt_template');
Ora puoi permettere agli utenti del plugin di copiare il template dal tuo plugin al loro tema per sovrascriverlo.
Con questo esempio, i template devono essere nella directory principale sia del plugin che del tema.

Utilizzare locate_template
invece di get_stylesheet_directory
mi sembra l'opzione più pulita (trovato qui: http://code.tutsplus.com/tutorials/a-guide-to-wordpress-custom-post-types-creation-display-and-meta-boxes--wp-27645).

La risposta aggiornata non ha funzionato, la risposta accettata (o la tua vecchia risposta) funziona.

Vorrei sottolineare che quando si utilizza il metodo del filtro per questo, è estremamente importante dare priorità al filtro in questo modo:
add_filter('single_template', 'my_custom_template', 99);
Se non lo fai, a volte WordPress tenterà di ricontrollare dopo questo filtro. Mi sono strappato i capelli per circa 2 ore a causa di questo.

Nei miei plugin utilizzo solitamente locate_template()
che rende possibile sovrascrivere i template del plugin copiandoli nel tema corrente:
function templateInclude(string $template): string
{
if (is_single() && get_query_var('post_type') === 'custom_post_type') {
$templates = [
'single-custom_post.php',
'templates/single-custom_post.php'
];
$template = locate_template($templates);
if (!$template) {
$template = __DIR__ . '/templates/single-custom_post.php';
}
}
return $template;
}
add_filter('template_include', 'templateInclude');
Ora l'utente può sovrascrivere il template del plugin copiandolo dalla cartella del plugin templates/single-custom_post.php
e posizionandolo sia direttamente nella root che in una cartella templates
all'interno del tema attivo.
Suppongo che si possa utilizzare lo stesso approccio anche quando si usa il filtro single_template
.

C'è un modo molto migliore per farlo che sto utilizzando per i miei plugin.
Come @campsjos ha menzionato qui, invece di controllare l'esistenza del file, puoi verificare
locate_template
che controllerà il file template sovrascritto dal tema. Il che è abbastanza ovvio.
function my_plugin_templates() {
if (is_singular('movie')) {
if (file_exists($this->template_dir . 'single-movie.php')) {
return $this->template_dir . 'single-movie.php';
}
}
}
Utilizza l'hook filter template_include
per caricare il codice sopra.
add_filter('template_include' , 'my_plugin_templates');

grazie a questa pagina ho potuto risolvere lo stesso problema per me.
Per riferimento, questo è ciò con cui ho finito:
function pluginName_myposttype_single_template($single_template) {
$myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';
return get_post_type() === 'myposttype' && file_exists($myposttype_template) ? $myposttype_template : $single_template;
}
add_filter('single_template', 'pluginName_myposttype_single_template');
l'hook del filtro {$type}_template non ha funzionato per me
function pluginName_myposttype_single_template($single_template) {
$myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';
if ( file_exists($myposttype_template) ) {
$single_template = $myposttype_template;
}
return $single_template;
}
add_filter('single-myposttype_template', 'pluginName_myposttype_single_template');

Questo funziona per me, per favore provalo, grazie
I template vengono caricati nel file cpt, che si trova in
custom_plugin -> app -> cpt -> cpt_article.php
Il template si trova in
custom_plugin -> app -> templates
add_filter( 'single_template', 'load_my_custom_template', 99, 1 );
function load_custom_templates($single_template) {
global $post;
if ($post->post_type == 'article' ) {
$single_template = trailingslashit( plugin_dir_path( __FILE__ ) .'app/templates' ).'single_article.php';
}
return $single_template;
}

La risposta sopra è ottima, ma verificare la variabile $single consente al template di sovrascrivere un template se ne viene fornito uno dal tema/tema child.
/* Filtra il single_template con la nostra funzione personalizzata */
add_filter('single_template', 'your_cpt_custom_template');
function your_cpt_custom_template( $single ) {
global $wp_query, $post;
/* Controlla il template single in base al post type */
if ( !$single && $post->post_type == 'cpt' ) {
if( file_exists( plugin_dir_path( __FILE__ ) . 'single-cpt.php' ) )
return plugin_dir_path( __FILE__ ) . 'single-cpt.php';
}
return $single;
}

Questo non controlla se single-cpt.php è presente in un child o nel tema. Controlla solo rispetto a single.php che sarà sempre presente in qualsiasi tema.
