Modèles de type de message personnalisé à partir du dossier du plug-in?

57

J'aimerais proposer mon type de message personnalisé sous forme de plug-in, afin que les gens puissent l'utiliser sans toucher à leur dossier de thèmes. Toutefois, les modèles de type de publication personnalisés, tels que single-movies.php, résident dans le dossier du thème. Existe-t-il un moyen de demander à WP de rechercher un fichier single-movies.php dans le dossier du plug-in? Accrocher une fonction dans la hiérarchie de Filer ? Ou get_template_directory (); ?

nathanbweb
la source

Réponses:

90

Vous pouvez utiliser le single_templatecrochet de filtre.

/* Filter the single_template with our custom function*/
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Checks for single template by post type */
    if ( $post->post_type == 'POST TYPE NAME' ) {
        if ( file_exists( PLUGIN_PATH . '/Custom_File.php' ) ) {
            return PLUGIN_PATH . '/Custom_File.php';
        }
    }

    return $single;

}
Bainternet
la source
C'est génial réponse. S'il vous plaît partager où puis-je obtenir tous les modèles disponibles crochet comme single_template.
Gowri
6
@gowri Le filtre est appelé par la get_query_template()fonction. C'est un crochet variable, donc la première partie {$type}_templatechange en fonction du paramètre passé à cette fonction. Voir wp-includes / template.php pour quelques exemples courants
karité
Ce tutoriel couvre le hook single_template avec une bonne explication. Une fois que vous avez compris les points faibles, le commentaire de @ shea suggère une approche plus simple que la réponse de @ Bainternet, en utilisant add_filter( 'single-movies_template', 'my_custom_template' );comme dans le tutoriel lié. (Cette question est fermée aux nouvelles réponses, je ne peux donc pas l'ajouter toute seule.)
Greg Perham
2
Vous pouvez remplacer PLUGIN_PATHpar plugin_dir_path( __FILE__ ), puis supprimer la première barre oblique de votre nom de fichier. Le chemin complet ressemblerait à ceci:return plugin_dir_path( __FILE__ ) . 'Custom_File.php';
Frits
1
PLUGIN_PATH a généré une erreur. Voici un excellent article qui explique comment faire cela et qui a fonctionné pour moi immédiatement
Nathan,
22

Réponse mise à jour

Version plus propre et plus courte.

function load_movie_template( $template ) {
    global $post;

    if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
        /*
         * This is a 'movie' post
         * AND a 'single movie template' is not found on
         * theme or child theme directories, so load it
         * from our plugin directory.
         */
        return plugin_dir_path( __FILE__ ) . 'single-movie.php';
    }

    return $template;
}

add_filter( 'single_template', 'load_movie_template' );

Ancienne réponse

Ajout d'une vérification pour un modèle spécifique de type d'article personnalisé dans le dossier de thèmes à @Brainternet answer.

function load_cpt_template($template) {
    global $post;

    // Is this a "my-custom-post-type" post?
    if ($post->post_type == "my-custom-post-type"){

        //Your plugin path 
        $plugin_path = plugin_dir_path( __FILE__ );

        // The name of custom post type single template
        $template_name = 'single-my-custom-post-type.php';

        // A specific single template for my custom post type exists in theme folder? Or it also doesn't exist in my plugin?
        if($template === get_stylesheet_directory() . '/' . $template_name
            || !file_exists($plugin_path . $template_name)) {

            //Then return "single.php" or "single-my-custom-post-type.php" from theme directory.
            return $template;
        }

        // If not, return my plugin custom post type template.
        return $plugin_path . $template_name;
    }

    //This is not my custom post type, do nothing with $template
    return $template;
}
add_filter('single_template', 'load_cpt_template');

Vous pouvez maintenant laisser les utilisateurs du plug-in copier le modèle de votre plug-in dans leur thème pour le remplacer.

Dans cet exemple, les modèles doivent figurer dans le répertoire racine du plugin et du thème.

campsjos
la source
1
Utiliser pour moi locate_templatedes get_stylesheet_directorysons comme l'option de nettoyage (trouvé ici: code.tutsplus.com/tutorials/… ).
Felix
1
La réponse mise à jour n'a pas fonctionné, la réponse acceptée (ou votre ancienne réponse) fonctionne.
Edward
2
Vous avez raison, @ Edward, c'était une mise à jour épouvantable. Je l'ai mis à jour à nouveau avec la suggestion de Félix. Aussi cette fois j'ai testé le code avant de le poster :)
campsjos le
4

Je tiens à souligner que lorsque vous utilisez la méthode de filtrage pour cela, il est extrêmement important de hiérarchiser le filtre de la manière suivante:

add_filter('single_template', 'my_custom_template', 99);

Si vous ne le faites pas, parfois, WP tentera de vérifier à nouveau après ce filtre. J'arrachais mes cheveux à cause de ça pendant 2 heures.

RBizzle
la source
0

Il existe une bien meilleure façon de le faire que j'utilise pour mes plugins.

Comme @campsjos le mentionne ici , au lieu de la vérification de l’existence du fichier, vous pouvez vérifier locate_templateque cela sera vérifié dans le fichier de modèle de remplacement de thème. Ce qui est assez évident.

function my_plugin_templates() {
    if (is_singular('movie')) {
        if (file_exists($this->template_dir . 'single-movie.php')) {
            return $this->template_dir . 'single-movie.php';
        }
    }
}

Utilisez le template_includecrochet de filtre pour charger le code ci-dessus.

add_filter('template_include' , 'my_plugin_templates');
pixelngrain
la source
0

Grâce à cette page, j'ai pu résoudre la même question pour moi.

Pour référence, voici ce que j'ai fini avec:

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');

le hook de filtre {$ type} _template n'a pas fonctionné pour moi

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');
Thomas Fellinger
la source
-2

La réponse ci-dessus est excellente, mais la vérification de la variable $ single permet au modèle de remplacer un modèle si celui-ci est fourni par le thème theme / child.

/* Filter the single_template with our custom function*/
add_filter('single_template', 'your_cpt_custom_template');

function your_cpt_custom_template( $single ) {
    global $wp_query, $post;
    /* Checks for single template by 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;
}
DigitalDesignDj
la source
1
Cela ne vérifie pas si single-cpt.php est présent dans un enfant ou dans le thème. Il ne vérifie que single.php qui sera toujours présent dans tous les thèmes.
newpxsn
C'est vrai, quand j'ai écrit ça, j'utilisais un thème vraiment dépouillé, il devait y avoir un meilleur moyen!
DigitalDesignDj