Créer un Custom Post Type dans WordPress
WordPress est livré avec les Publications et les Pages, mais ces deux types de contenu ne vous mèneront pas loin lorsqu’un client a besoin d’un annuaire de biens immobiliers, d’une liste du personnel ou d’une archive de recettes. C’est là qu’intervient un custom post type WordPress — une structure de contenu de premier ordre qui s’intègre proprement dans le modèle de données existant de WordPress sans bidouiller les paramètres par défaut.
Points clés à retenir
- Un custom post type (CPT) étend la table partagée
wp_postsplutôt que d’en créer une séparée, vous offrant des écrans d’administration, des endpoints REST API et un routage de templates prêts à l’emploi. - Enregistrez toujours les CPT dans une extension, pas dans un thème, afin que le contenu reste accessible indépendamment des changements de thème.
- Définir
show_in_restsurtrueest requis pour la prise en charge de l’éditeur de blocs et l’exposition via l’API REST. - Videz les règles de réécriture uniquement lors de l’activation de l’extension — jamais à chaque chargement de page.
Qu’est-ce qu’un Custom Post Type ?
Un custom post type (CPT) est un type de contenu nommé que vous enregistrez auprès de WordPress. Malgré son nom, ce n’est pas une table de base de données séparée. Tous les types de publication — natifs et personnalisés — partagent la table wp_posts, différenciés par la colonne post_type. C’est un modèle mental important : vous étendez une structure existante, vous n’en créez pas une parallèle.
Les types de publication par défaut incluent post, page, attachment, revision et nav_menu_item. Lorsque vous enregistrez un CPT comme property ou recipe, WordPress le traite avec la même cohérence : écrans d’administration, endpoints REST API, routage d’URL et hiérarchie de templates fonctionnent tous de la même manière.
Custom post types ≠ champs personnalisés. Un CPT définit le type de contenu. Les champs personnalisés (ajoutés via ACF ou l’API de métadonnées) stockent des données supplémentaires attachées à ce contenu. Ce sont des préoccupations distinctes.
Enregistrer un Custom Post Type avec register_post_type()
La méthode canonique pour créer un custom post type WordPress est la fonction register_post_type(), appelée sur le hook init.
Voici un exemple propre et fonctionnel :
add_action( 'init', 'register_property_post_type' );
function register_property_post_type() {
$labels = [
'name' => 'Properties',
'singular_name' => 'Property',
'add_new_item' => 'Add New Property',
'edit_item' => 'Edit Property',
'not_found' => 'No properties found.',
];
$args = [
'labels' => $labels,
'public' => true,
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'rewrite' => [ 'slug' => 'properties' ],
'show_in_rest' => true,
];
register_post_type( 'property', $args );
}
Explication des arguments clés
public— Rend le CPT visible dans l’administration et sur le front-end. Définissez surfalsepour les types à usage interne uniquement.labels— Contrôle toutes les chaînes de l’interface utilisateur dans l’administration. Il vaut la peine de les remplir correctement pour que les éditeurs ne soient pas confus.supports— Déclare quelles fonctionnalités de l’éditeur apparaissent sur l’écran d’édition. Valeurs courantes :title,editor,thumbnail,excerpt,custom-fields.has_archive— Active une page d’archive à/properties/. WordPress cherchera un templatearchive-property.phpcorrespondant (ou se rabattra surarchive.php).rewrite— Définit le slug d’URL. Les publications individuelles apparaîtront à/properties/nom-publication/.show_in_rest— Définissez ceci surtrue. Cela expose le CPT via l’API REST WordPress et est requis pour que l’éditeur de blocs fonctionne correctement avec votre type de publication. Sans cela, l’éditeur revient à l’interface classique.
Discover how at OpenReplay.com.
Extension vs. Thème : où le code doit-il résider ?
C’est un point de confusion courant. Enregistrez votre custom post type dans une extension, pas dans un thème.
Si l’enregistrement de votre CPT se trouve dans functions.php et que le client change de thème, tout le contenu de ce type devient inaccessible — non supprimé, mais invisible. Une extension dédiée (même une simple extension à un seul fichier) maintient le CPT actif indépendamment des changements de thème.
Ne videz pas les règles de réécriture à chaque requête. Appelez
flush_rewrite_rules()une seule fois — lors de l’activation de l’extension viaregister_activation_hook(). Vider à chaqueinitest un problème de performance.
Hiérarchie de templates pour les Custom Post Types
WordPress recherche les templates dans cet ordre pour une entrée CPT individuelle :
single-{post-type}.php(par ex.,single-property.php)single.phpsingular.phpindex.php
Pour les archives, il suit : archive-{post-type}.php → archive.php → index.php.
Conclusion
Avec register_post_type() correctement accroché à init, show_in_rest activé, et l’enregistrement résidant dans une extension, vous disposez d’une base solide et portable. À partir de là, vous pouvez ajouter des taxonomies personnalisées, des champs méta via ACF ou l’API de métadonnées, et des colonnes d’administration personnalisées — sans toucher à quoi que ce soit qui pourrait casser lors des mises à jour de WordPress ou de votre thème.
FAQ
Le contenu reste dans la table wp_posts et n'est pas supprimé. Cependant, WordPress ne reconnaît plus ce type de publication, donc les publications deviennent invisibles dans l'administration et sur le front-end. Réactiver l'extension restaure immédiatement l'accès. C'est pourquoi l'enregistrement des CPT doit toujours résider dans une extension dédiée plutôt que dans un thème.
Oui. Vous pouvez appeler register_post_type() plusieurs fois au sein du même callback init ou utiliser des callbacks séparés accrochés à init. Il n'y a pas de limite au nombre de custom post types qu'une seule extension peut enregistrer, bien que chacun doive avoir un slug de type de publication unique ne dépassant pas 20 caractères.
Cela signifie presque toujours que les règles de réécriture doivent être vidées. Visitez Réglages puis Permaliens dans l'administration WordPress et cliquez sur Enregistrer les modifications. Cela déclenche un vidage de la réécriture. Pour les extensions, appelez flush_rewrite_rules() à l'intérieur de register_activation_hook() pour qu'il s'exécute automatiquement lors de l'activation. Ne videz jamais à chaque chargement de page.
Pas strictement, mais c'est tout de même recommandé. Définir show_in_rest sur true expose votre type de publication via l'API REST WordPress, ce qui est utile pour les configurations headless, les intégrations externes et la compatibilité future. Si vous passez un jour à l'éditeur de blocs, il fonctionnera déjà correctement.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.