
⚙️ WordPress : comment définir un modèle par défaut pour un type de publication personnalisé
Vous remettez au client un site sous WordPress avec un portfolio, et il vous rappelle le lendemain: «J’ajoute une nouvelle entrée, mais le template revient systématiquement à celui par défaut avec une barre latérale. Comment le verrouiller?» La situation est douloureusement familière: vous cliquez sur «Ajouter» dans un type de contenu personnalisé, et au lieu de la mise en page pleine largeur que vous avez conçue, vous obtenez une colonne de blog avec une sidebar. Devoir choisir le template manuellement pour chaque publication est une corvée inutile qui frustre autant vous que le client. Surtout quand «Pleine largeur» sans barre latérale est ce dont vous avez besoin presque à chaque fois.
Par défaut, WordPress utilise single.php du thème pour les types de contenu personnalisés (CPT). Et single.php est généralement taillé pour un blog: titre, contenu, sidebar avec des widgets. Pour des portfolios, des études de cas, des témoignages ou des produits, cette mise en page est peu adaptée. Bonne nouvelle: WordPress propose quatre façons d’attribuer un template à un CPT, de la plus simple (un fichier dans le thème, sans aucune ligne de code) à une approche entièrement programmatique via des hooks et les thèmes en blocs. Chaque méthode fait le travail de manière fiable; la seule différence réside dans le niveau de contrôle et la facilité de maintenance.
💡 Aperçu rapide:
- Créez un fichier
single-{post_type}.phpà la racine du thème, et WordPress le détectera automatiquement via la hiérarchie des templates - Utilisez le filtre
template_includedansfunctions.phppour attribuer un template de manière programmatique sans placer de fichier physique dans le thème - Pour les thèmes en blocs, créez
single-{post_type}.htmldans le dossiertemplates/; il peut être modifié via l’éditeur de site sans code - Après toute modification, régénérez les permaliens: «Réglages → Permaliens → Enregistrer les modifications», sinon WordPress ne verra pas le nouveau template
Méthode 1: fichier de template via la hiérarchie WordPress
La méthode la plus fiable et la plus directe. Depuis la version 3.0, WordPress prend en charge les templates personnalisés pour les CPT via la hiérarchie standard des templates. Voici comment cela fonctionne: lorsqu’un visiteur ouvre une entrée de type portfolio, WordPress cherche un template dans un ordre strict, de haut en bas, et utilise le premier fichier trouvé:
single-portfolio.php → single.php → singular.php → index.php
Vous devez créer un fichier nommé single-{post_type}.php, où {post_type} est le slug de votre type personnalisé. Placez-le à la racine du thème actif:
1 /* File: /wp-content/themes/your-theme/single-portfolio.php */ 2 3 <?php get_header(); ?> 4 5 <div class="full-width-content"> 6 <?php while ( have_posts() ) : the_post(); ?> 7 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 8 <h1><?php the_title(); ?></h1> 9 <div class="entry-content"> 10 <?php the_content(); ?> 11 </div> 12 </article> 13 <?php endwhile; ?> 14 </div> 15 16 <?php get_footer(); ?> 17
La manière la plus rapide de commencer: copiez le contenu de page.php ou de template-fullwidth.php de votre thème et adaptez la mise en page au CPT concerné. Si aucun fichier single-{post_type}.php n’existe, WordPress bascule silencieusement sur single.php, et le client se retrouve avec une barre latérale.
L’avantage de cette méthode: pas de code dans functions.php; le fichier est simplement présent dans le thème et fonctionne. L’inconvénient: le template est étroitement lié au thème. Si vous changez de thème, le fichier reste dans l’ancien dossier et cesse de fonctionner.
Méthode 2: de manière programmatique via le filtre template_include
La méthode par fichier fonctionne tant que vous contrôlez le thème. Mais si vous développez une extension ou un thème enfant qui ne doit pas dépendre de la présence d’un fichier à la racine, vous avez besoin du hook template_include.
Le filtre se déclenche avant le chargement du template et vous permet de pointer vers un fichier PHP depuis n’importe quel emplacement:
1 /* File: functions.php (theme) or main plugin file */ 2 3 add_filter( 'template_include', 'sd_cpt_default_template', 99 ); 4 5 function sd_cpt_default_template( $template ) { 6 if ( is_singular( 'portfolio' ) ) { 7 $custom_template = plugin_dir_path( __FILE__ ) . 'templates/single-portfolio.php'; 8 if ( file_exists( $custom_template ) ) { 9 return $custom_template; 10 } 11 } 12 return $template; 13 }
Voici ce qui se passe ici:
is_singular('portfolio')vérifie si nous sommes sur la page d’une entrée unique du typeportfolio- Si la condition est vraie, WordPress charge le template depuis le dossier de l’extension, en contournant la hiérarchie du thème
- La priorité 99 garantit que le filtre se déclenche en dernier et n’est pas écrasé par le thème
Cette approche est pratique lorsque le template doit résider dans une extension et survivre aux changements de thème. Le fichier templates/single-portfolio.php à l’intérieur de l’extension peut utiliser get_header() et get_footer() du thème actif, de sorte que visuellement tout reste cohérent avec le design du site.
Méthode 3: le filtre {$type}_template
WordPress fournit un hook dynamique {$type}_template, où $type est single, archive ou page. Pour un CPT, il prend la forme single-portfolio_template et vous permet de surcharger le template avec précision, sans vérifications supplémentaires à l’intérieur de la fonction de rappel:
1 add_filter( 'single_template', 'sd_cpt_template_by_type' ); 2 3 function sd_cpt_template_by_type( $single_template ) { 4 global $post; 5 6 if ( 'portfolio' === $post->post_type ) { 7 $custom_template = get_stylesheet_directory() . '/single-portfolio.php'; 8 if ( file_exists( $custom_template ) ) { 9 return $custom_template; 10 } 11 } 12 return $single_template; 13 }
La différence par rapport à la méthode 2 est sémantique: vous dites explicitement «changer le template pour les entrées uniques» au lieu de «intercepter tous les templates». Le code est légèrement plus propre, mais fonctionnellement les deux hooks résolvent le problème de la même manière.
Méthode 4: template dans un thème en blocs (Full Site Editing)
À partir de WordPress 5.9 et du passage aux thèmes en blocs, l’approche change. Dans les thèmes FSE, les templates sont des fichiers HTML dans le dossier templates/, pas des fichiers PHP. Pour un type de contenu personnalisé, créez:
1 /wp-content/themes/your-fse-theme/templates/single-portfolio.html
À l’intérieur, vous utilisez une structure basée sur des blocs. Un exemple minimal:
1 <!-- wp:template-part {"slug":"header","theme":"your-fse-theme"} /--> 2 3 <!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} --> 4 <main class="wp-block-group"> 5 <!-- wp:post-title {"level":1} /--> 6 <!-- wp:post-featured-image /--> 7 <!-- wp:post-content {"layout":{"type":"constrained"}} /--> 8 </main> 9 <!-- /wp:group --> 10 11 <!-- wp:template-part {"slug":"footer","theme":"your-fse-theme"} /-->
Vous pouvez modifier ce template directement dans l’éditeur de site (Apparence → Éditeur) sans toucher au code. Si vous changez de thème en blocs, le fichier reste dans l’ancien dossier, la même vulnérabilité que la méthode 1.
Quelle méthode choisir
Une matrice de décision rapide pour votre scénario:
Scénario | Méthode |
|---|---|
Un thème, un CPT, pas d’extension | Méthode 1: |
Extension avec son propre template | Méthode 2: |
Thème enfant, besoin de surcharger le template parent | Méthode 1 ou 3 |
FSE / thème en blocs (Twenty Twenty-Four et plus récents) | Méthode 4: |
Après avoir implémenté l’une de ces méthodes, pensez à aller dans «Réglages → Permaliens» et à cliquer sur «Enregistrer les modifications». Cela vide le cache des règles de réécriture, et WordPress commence à reconnaître le nouveau template.
⁉️🤔 Questions fréquentes
Le template n’est pas pris en compte. Que dois-je faire?
D’abord, régénérez les permaliens («Réglages → Permaliens → Enregistrer»). Ensuite, vérifiez que le slug du CPT dans le nom du fichier correspond au slug de
register_post_type(). Enfin, si une extension de cache est active, videz le cache. En pratique, le problème vient le plus souvent de l’oubli de vider les règles de réécriture après l’enregistrement du CPT, pas du code du template lui-même.
Puis-je attribuer un même template à plusieurs CPT à la fois?
Oui. Avec la méthode 2, utilisez un tableau dans
is_singular():is_singular( array( 'portfolio', 'testimonials', 'team' ) ). Ou vérifiezin_array( $post->post_type, array('portfolio', 'team') )à l’intérieur de la fonction de rappel. Le fichier de template est unique, et la mise en page sera partagée par tous les types listés.
Le template fonctionne, mais la mise en page est cassée (styles de la sidebar ou de l’en-tête manquants).
Vous avez hérité le template de
page.php, mais les styles du thème dépendent des classes CSS surbody. Ajoutez un filtrebody_classdansfunctions.phppour que WordPress applique une classepost-type-{slug}à<body>, et les styles s’appliqueront:
1 add_filter( 'body_class', function( $classes ) { 2 if ( is_singular( 'portfolio' ) ) { 3 $classes[] = 'single-portfolio'; 4 } 5 return $classes; 6 } );
Que se passe-t-il quand je change de thème? Le template disparaît.
Oui, le fichier
single-portfolio.phpreste dans le dossier de l’ancien thème. Vos options: déplacer le fichier manuellement vers le nouveau thème, utiliser un thème enfant (le fichier survit aux mises à jour du thème parent), ou déplacer le template dans une extension via la méthode 2, qui ne dépend pas du thème actif.
Et si j’ai besoin que TOUS les CPT s’ouvrent sans barre latérale par défaut?
Utilisez un filtre universel avec
is_singular()sans spécifier de post_type particulier, mais excluez les typespostetpagestandards:
1 add_filter( 'template_include', function( $template ) { 2 if ( is_singular() && ! is_singular( array( 'post', 'page' ) ) ) { 3 $fullwidth = get_stylesheet_directory() . '/template-fullwidth.php'; 4 if ( file_exists( $fullwidth ) ) { 5 return $fullwidth; 6 } 7 } 8 return $template; 9 }, 99 );
Cette solution applique un seul template pleine largeur à tous les types de contenu personnalisés en une fois: portfolios, témoignages, membres de l’équipe, études de cas. Les articles et pages standards ne sont pas affectés.
Est-ce que cela vaut la peine de s’embêter avec template_include alors qu’on peut simplement créer un fichier?
Si vous avez un site, un thème et un CPT, créez single-{post_type}.php et n’y pensez plus. C’est une solution qui dure des années: elle ne casse pas lors des mises à jour de WordPress, ne dépend pas de la version de PHP et est immédiatement compréhensible pour tout développeur qui ouvre le dossier du thème. La maintenance se résume à un seul fichier que vous pouvez corriger en un rien de temps.
Les méthodes programmatiques via des hooks se justifient dans deux cas. Premier cas: le template fait partie d’une extension distribuée, et vous ne voulez pas imposer aux utilisateurs de copier des fichiers dans le thème. Second cas: les CPT sont enregistrés dynamiquement via ACF, Toolset ou une extension similaire, et multiplier une douzaine de fichiers single-*.php dans le thème n’est pas pratique. Pour tout le reste, la hiérarchie des templates de WordPress est la voie la plus simple et la plus fiable, éprouvée au fil des années.



