Projet Niveau 2 — Plugin « Bibliothèque » (CPT Livre)
⏱️ TL;DR — Votre premier vrai plugin, et le début du fil rouge
wpr-books. Vous enregistrez un Custom Post Type « Livre », une taxonomie « Genre », des champs personnalisés (ISBN, prix) via une metabox, un shortcode qui liste le catalogue, et une page de réglages (Settings API). Objectif : maîtriser le triptyque hooks / enregistrement / sécurité qui fonde tout développement WordPress.
🎯 Niveau & objectifs
- Niveau : 2 (intermédiaire). Prérequis : Niveaux 0–1 ; bases de PHP ;
WP_DEBUGactivé. - Durée indicative : 6–10 h.
- Vous allez pratiquer : structure d’un plugin,
add_action/add_filter,register_post_type,register_taxonomy, metaboxes,register_post_meta, Settings API, shortcodes, sécurité (nonces,sanitize_*,esc_*, capabilities).
📋 Cahier des charges
Contexte — Une petite librairie veut gérer un catalogue de livres structuré dans WordPress, sans bidouiller des articles. Vous livrez le plugin socle. (C’est wpr-books, qui grandira aux niveaux 3, 4, 5.)
Objectif — Un plugin autonome, activable/désactivable proprement, qui ajoute un type de contenu « Livre » complet et l’affiche en front.
Périmètre inclus
- En-tête de plugin correct + activation/désactivation (avec
flush_rewrite_rulesau bon moment). - CPT
wpr_book(« Livre ») :public,show_in_rest: true, support titre/éditeur/thumbnail, réécriture d’URLlivres/. - Taxonomie
wpr_genre(« Genre »), hiérarchique,show_in_rest. - Champs meta :
wpr_isbn(texte) etwpr_prix(nombre), enregistrés viaregister_post_metaet édités via une metabox (avec nonce). - Un shortcode
[wpr_books genre="..." limit="..."]listant les livres viaWP_Query. - Une page de réglages (Settings API) : ex. « nombre de livres par page par défaut », « devise ».
- Chargement des traductions (
load_plugin_textdomain) et chaînes traduisibles.
Périmètre exclu — Pas de bloc Gutenberg (Niveau 3), pas de REST custom (Niveau 3), pas de front Next.js (Niveau 4). On reste PHP + admin + shortcode.
Contraintes
- Aucune donnée non filtrée ne rentre en base (
sanitize_*), aucune donnée non échappée ne sort (esc_*). - Sauvegarde de la metabox protégée par nonce +
current_user_can. - Préfixe
wpr_partout (fonctions, options, meta) pour éviter les collisions. - Code organisé (au moins séparé en quelques fichiers
includes/).
Livrables
- Le dossier du plugin (zippable, installable sur une autre instance).
- Un
readmecourt : ce que fait le plugin, le shortcode et ses attributs.
✅ Critères de réussite
- Le menu « Livres » apparaît dans l’admin ; on peut créer un livre avec ISBN et prix.
- Les livres sont accessibles en front sur
/livres/<slug>(permaliens rafraîchis). - La metabox refuse une sauvegarde sans nonce valide.
- Le shortcode affiche le catalogue, filtrable par genre, respectant la limite.
- Les champs
wpr_isbn/wpr_prixapparaissent dans/wp-json/wp/v2/wpr_book(grâce àshow_in_rest+register_post_meta). - Désactiver le plugin retire le menu ; aucune erreur PHP dans
debug.log.
🗺️ Endroits à visiter
| Endroit | Où | Pourquoi y aller |
|---|---|---|
Dossier wp-content/plugins/ | filesystem | Ouvrez 2–3 plugins simples existants : voir une vraie structure |
register_post_type (doc) | dev.wordpress.org | Tous les arguments (rewrite, show_in_rest, supports) |
Hooks init, save_post, admin_menu | Plugin Handbook | Les points d’accroche que vous allez utiliser |
/wp-json/wp/v2/ | navigateur | Voir votre CPT apparaître dans l’API (prépare le Niv. 3–4) |
WP_DEBUG + debug.log | wp-config.php / wp-content/ | Votre console : activez-le, gardez-le ouvert |
| WP-CLI | terminal | wp post list --post_type=wpr_book, wp plugin list |
| Settings API (doc) | Plugin Handbook | Le pattern officiel de page d’options |
Core : wp-includes/post.php | filesystem | Lire comment le core enregistre ses propres types |
💡 Pour un dev React — Un plugin, c’est un module qui s’accroche au cycle de vie via des hooks — pensez aux
useEffect/listeners, mais côté serveur et déclaratifs.register_post_type≈ définir un modèle de données + ses routes d’un coup (comme un schéma Prisma qui génèrerait aussi l’admin et l’API REST). La discipline nouvelle : sanitize à l’entrée, escape à la sortie — non négociable, c’est la base de la sécurité WordPress.
⚠️ Piège —
register_post_typedoit tourner sur le hookinit, jamais directement au chargement du fichier. Et pensez àflush_rewrite_rulesà l’activation (une seule fois), sinon vos URLs/livres/...renvoient un 404 fantôme.
🚀 Étapes suggérées
- En-tête de plugin + fichier principal ; activer le plugin vide.
register_post_type('wpr_book')surinit; créer un livre de test.- Hook d’activation :
flush_rewrite_rules. Vérifier l’URL front. register_taxonomy('wpr_genre'); classer des livres.register_post_meta+ metabox (affichage + sauvegarde avec nonce).- Shortcode
[wpr_books]viaWP_Query. - Page de réglages (Settings API).
- i18n : envelopper les chaînes, charger le textdomain.
- Relecture sécurité : chaque entrée
sanitize, chaque sortieesc.
🎁 Bonus
- Ajoutez une colonne « Prix » à la liste d’admin des livres (
manage_{post_type}_posts_columns). - Rendez
wpr_prixtriable dans l’admin. - Ajoutez une capability custom (
manage_wpr_books) plutôt quemanage_options.
🔗 Chapitres du cours liés
Projet suivant : Niveau 3 — Bloc « Livre à la une » + REST.