Publié sur Google Google
Clémence De Bastier profile picture
Clémence De Bastier
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Super prestataire, réactif et professionnel.
Publié sur Google Google
Service client weprecious profile picture
Service client weprecious
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Excellente expérience avec Aurelien et son Equipe. Tres réactifs et compétents. Je recommande.
Publié sur Google Google
Thom profile picture
Thom
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Je recommande les services d'Aurélien, disponible, pro et réactif !
Publié sur Google Google
Aude Sorey profile picture
Aude Sorey
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Merci pour votre aide. Rien ne fonctionnait et il ne faut pas s'étonner quand c'est un ami qui fait le site gratuitement, d'avoir des bugs ! Je recommande vos services avec plaisir à mes contacts.
Publié sur Google Google
Kevin Concha profile picture
Kevin Concha
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Aurelien a tout de suite compris mes attentes, et il m'a fait un site à la hauteur de mes exigences et est très minutieux dans les délais. J'ai d'autres sites à créer, c'est sans hésitation que je passerai par lui. Merci
Publié sur Google Google
Cédric APEP profile picture
Cédric APEP
Google star 1Google star 2Google star 3Google star 4Google star 5Trustindex vérifie que la source originale de l'avis est Google.
Rapide et efficace
Dévelopeur qui se former au développement de plugin WordPress

Pour créer un plugin WordPress, il suffit d’un dossier placé dans wp-content/plugins/ et d’un fichier PHP qui commence par un en-tête contenant au moins la ligne Plugin Name. Le plugin agit ensuite sur WordPress par des hooks : des actions pour exécuter du code à un moment précis, des filtres pour modifier une valeur. Les bases de PHP suffisent pour démarrer ; le reste s’apprend en construisant, à condition de prendre tout de suite les bons réflexes de sécurité.

Vous allez écrire ici un premier plugin complet et commenté, puis découvrir les outils actuels (blocs, environnement local, Plugin Check), la sécurité, les traductions, les tests, la publication et les ressources gratuites pour continuer. Le guide est à jour de WordPress 7.1. Je suis développeur WordPress depuis quatorze ans et je crée des extensions pour les sites de mes clients : ce sont les bases et les réflexes que je considère comme indispensables avant d’écrire la vôtre.

Ce qu’il faut savoir avant de créer un plugin WordPress

Les langages : PHP d’abord, JavaScript moderne ensuite

Le cœur d’un plugin est écrit en PHP : fonctions, tableaux, conditions, puis les bases de la programmation orientée objet dès que le code grossit. Il faut aussi savoir écrire du HTML et du CSS pour ce que l’extension affiche. Le JavaScript devient indispensable si vous créez des blocs : l’éditeur de WordPress repose sur React et sur les paquets @wordpress/*. jQuery, longtemps incontournable, n’est plus nécessaire pour écrire une interface moderne.

Le SQL passe au second plan : la plupart des données se rangent avec les API de WordPress (options, métadonnées, types de contenu personnalisés, API REST). Quand une requête SQL est vraiment nécessaire, elle passe par l’objet $wpdb et sa méthode prepare().

Côté versions, WordPress 7.0 a relevé le minimum à PHP 7.4, mais WordPress.org recommande PHP 8.3 ou plus. Côté PHP, seules les branches 8.2 à 8.5 sont encore maintenues en octobre 2026, et la 8.2 cessera de recevoir des correctifs de sécurité le 31 décembre 2026 (calendrier de php.net). Testez donc votre code sous les versions récentes, et déclarez dans l’en-tête la version minimale qu’il prend réellement en charge.

L’environnement de travail

On ne développe jamais une extension directement sur un site en ligne. Il vous faut :

  • un WordPress local : wp-env, l’outil officiel basé sur Docker, démarre un site de test depuis le dossier de votre plugin et l’active automatiquement ; tout autre outil de site local fait aussi l’affaire ;
  • WordPress Playground, pour essayer une idée ou une extension directement dans le navigateur, sans rien installer ;
  • un éditeur de code comme Visual Studio Code ou PhpStorm, configuré avec les règles de codage de WordPress ;
  • Git, pour versionner chaque modification et revenir en arrière en cas de besoin ;
  • le mode débogage activé en local (voir plus bas), pour voir chaque avertissement PHP au lieu de le découvrir en production.
# Une seule fois : installer wp-env (Node.js et Docker requis)
npm -g install @wordpress/env

# Depuis le dossier de votre extension : site local sur http://localhost:8888
wp-env start

Avant la mise en ligne, une préproduction (une copie du site réel) permet ensuite de tester l’extension avec le thème et les autres extensions du site. Sur les sites que je maintiens, c’est en préproduction que je teste les mises à jour avant de les appliquer : une nouvelle extension mérite le même traitement.

Plugin ou functions.php : où placer son code ?

La règle est simple : ce qui touche à l’apparence va dans le thème, de préférence un thème enfant ; ce qui est une fonctionnalité va dans un plugin. Un type de contenu, un shortcode, une connexion à une API ou un réglage d’administration doivent survivre à un changement de thème : leur place est dans une extension, même minuscule et propre à un seul site. Pour la partie apparence, voyez ce qui a sa place dans un thème enfant.

Et si vous voulez seulement changer le comportement d’une extension déjà installée, inutile de la réécrire : il existe plusieurs méthodes pour modifier une extension existante sans toucher à ses fichiers.

Développeur WordPress qui apprend à créer un plugin

Créer son premier plugin WordPress pas à pas

Le fil rouge de cette partie : une petite extension qui affiche le temps de lecture estimé d’un article grâce au shortcode [devwp_reading_time]. Elle tient en un seul fichier, mais applique déjà les règles d’une extension publiable.

Étape 1 : créer le dossier et le fichier principal

Dans wp-content/plugins/, créez un dossier devwp-reading-time, puis à l’intérieur un fichier devwp-reading-time.php. Le nom du dossier est le « slug » de l’extension : unique, en minuscules, avec des tirets. Choisissez aussi un préfixe (ici devwp_rt_) à placer devant toutes vos fonctions, options et identifiants : WordPress et toutes les extensions partagent le même espace de noms, et deux fonctions homonymes provoquent une erreur fatale.

Quand l’extension grandit, son arborescence ressemble généralement à ceci :

  • devwp-reading-time.php : le fichier principal, avec l’en-tête ;
  • includes/ : les classes et fonctions PHP ;
  • assets/ : CSS, JavaScript et images ;
  • languages/ : les fichiers de traduction ;
  • uninstall.php : le nettoyage à la suppression ;
  • readme.txt : la description, obligatoire pour le répertoire officiel.

Étape 2 : écrire l’en-tête du plugin

WordPress reconnaît une extension grâce au bloc de commentaires placé en haut de son fichier principal. Seul Plugin Name est obligatoire, mais les autres champs d’en-tête évitent bien des problèmes :

  • Version : la version de votre extension, que WordPress compare pour proposer les mises à jour ;
  • Requires at least et Requires PHP : les versions minimales de WordPress et de PHP ; WordPress refuse d’activer l’extension sur un site qui ne les atteint pas ;
  • License : une licence compatible avec la GPL (ici GPL-2.0-or-later), condition pour être accepté sur WordPress.org ;
  • Text Domain et Domain Path : l’identifiant des traductions, identique au slug, et le dossier des fichiers de langue ;
  • Requires Plugins, apparu avec WordPress 6.5 : la liste des extensions de WordPress.org dont la vôtre dépend ;
  • Update URI, introduit avec WordPress 5.8 : pour une extension diffusée hors du répertoire, il évite qu’une extension homonyme de WordPress.org soit proposée comme « mise à jour » et écrase la vôtre.

Étape 3 : comprendre les hooks (actions et filtres)

Une extension ne modifie pas les fichiers de WordPress : elle se branche sur des hooks, des points d’accroche prévus dans le code du cœur, des thèmes et des autres extensions.

  • Une action exécute votre fonction à un moment donné : add_action( 'init', 'ma_fonction' ) lance ma_fonction() une fois WordPress chargé, avant l’affichage de la page.
  • Un filtre reçoit une valeur, vous laisse la modifier et doit la retourner : c’est le rôle de add_filter().

Exemple de filtre qui raccourcit les extraits automatiques à 30 mots :

/**
 * Raccourcit les extraits automatiques à 30 mots.
 *
 * @param int $length Nombre de mots prévu par WordPress ou le thème.
 * @return int Nombre de mots à utiliser.
 */
function devwp_excerpt_length( $length ) {
	if ( is_admin() ) {
		return $length; // Ne rien changer dans l'administration.
	}
	return 30; // Un filtre doit toujours retourner une valeur.
}
add_filter( 'excerpt_length', 'devwp_excerpt_length', 20 );

Le troisième argument est la priorité (10 par défaut) : à 20, la fonction s’exécute après celles branchées avec la priorité par défaut et l’emporte donc sur elles. L’erreur la plus fréquente avec un filtre est d’oublier le return : la valeur devient alors null, et ce qu’elle contenait disparaît de la page.

Étape 4 : le code complet d’un plugin minimal

Voici le contenu complet de devwp-reading-time.php. Les textes sont écrits en anglais : c’est la convention de WordPress, la traduction française vient ensuite.

<?php
/**
 * Plugin Name:       DevWP Reading Time
 * Description:       Displays the estimated reading time of a post with the devwp_reading_time shortcode.
 * Version:           1.0.0
 * Requires at least: 6.8
 * Requires PHP:      7.4
 * Author:            Votre nom
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       devwp-reading-time
 * Domain Path:       /languages
 */

// Bloque l'accès direct au fichier, hors de WordPress.
defined( 'ABSPATH' ) || exit;

/**
 * Enregistre le shortcode une fois WordPress initialisé.
 */
function devwp_rt_register_shortcode() {
	add_shortcode( 'devwp_reading_time', 'devwp_rt_render_shortcode' );
}
add_action( 'init', 'devwp_rt_register_shortcode' );

/**
 * Calcule et retourne le temps de lecture de l'article courant.
 *
 * @param array|string $atts Attributs du shortcode.
 * @return string HTML échappé.
 */
function devwp_rt_render_shortcode( $atts ) {
	$atts = shortcode_atts(
		array( 'wpm' => 200 ), // Mots lus par minute, par défaut.
		$atts,
		'devwp_reading_time'
	);

	$post = get_post();
	if ( ! $post ) {
		return '';
	}

	$text    = wp_strip_all_tags( strip_shortcodes( $post->post_content ) );
	$words   = preg_split( '/\s+/u', $text, -1, PREG_SPLIT_NO_EMPTY );
	$count   = is_array( $words ) ? count( $words ) : 0;
	$wpm     = (int) $atts['wpm'];
	$wpm     = $wpm > 0 ? $wpm : 200; // Valeur nulle, négative ou non numérique : retour au défaut.
	$minutes = max( 1, (int) ceil( $count / $wpm ) );

	$label = sprintf(
		/* translators: %d: number of minutes. */
		_n( 'Reading time: %d minute', 'Reading time: %d minutes', $minutes, 'devwp-reading-time' ),
		$minutes
	);

	return '<p class="devwp-reading-time">' . esc_html( $label ) . '</p>';
}

Ce qu’il faut retenir de ce code :

  • defined( 'ABSPATH' ) || exit; empêche d’exécuter le fichier en l’appelant directement par son URL, hors de WordPress ;
  • le shortcode est enregistré sur le hook init, et toutes les fonctions portent le préfixe devwp_rt_ ;
  • shortcode_atts() fixe les valeurs par défaut et ignore les attributs inconnus ; l’attribut wpm (mots par minute) est converti en entier, et toute valeur nulle, négative ou non numérique ramène au réglage par défaut de 200 (absint() ne suffirait pas ici : il transforme -5 en 5) ;
  • preg_split() avec le modificateur u compte correctement les mots accentués, là où str_word_count() coupe « développeur » en deux ;
  • _n() choisit entre singulier et pluriel, et le commentaire translators: explique aux traducteurs ce que représente %d ;
  • esc_html() échappe la sortie, et la fonction retourne son HTML au lieu de l’afficher avec echo : un shortcode qui affiche directement son texte le fait apparaître avant le contenu, hors de sa place.

Une limite à connaître : strip_shortcodes() retire aussi le texte placé à l’intérieur des shortcodes. Sur un site construit avec un constructeur de pages à base de shortcodes, comme Avada, le calcul serait faussé et devrait être adapté. C’est le genre de détail qui n’apparaît qu’en testant sur un vrai site.

Étape 5 : installer, activer et tester

Si vous avez créé le dossier directement dans wp-content/plugins/ de votre site local, l’extension apparaît déjà dans le menu Extensions. Sinon, compressez le dossier au format ZIP et passez par Extensions > Ajouter une extension > Téléverser une extension. Activez-la, ajoutez [devwp_reading_time] dans un article, ou [devwp_reading_time wpm=250] pour un lecteur plus rapide, puis affichez l’article. Si la page affiche une erreur critique, le journal de débogage (voir plus bas) indique le fichier et la ligne en cause.

Aller plus loin : blocs, scripts et structure

Créer un bloc Gutenberg avec @wordpress/create-block

Un shortcode fonctionne partout, mais l’éditeur de WordPress est construit autour des blocs. Pour en créer un, l’outil officiel @wordpress/create-block génère en une commande une extension complète : fichier block.json qui décrit le bloc, code React pour l’éditeur, rendu, et chaîne de compilation fournie par @wordpress/scripts.

# Génère une extension contenant un bloc (Node.js requis)
npx @wordpress/create-block@latest devwp-mon-bloc --variant dynamic
cd devwp-mon-bloc
npm start       # compile en continu pendant le développement
npm run build   # version optimisée, à livrer

Lancez la commande depuis le dossier wp-content/plugins/ de votre site local, ou démarrez wp-env dans le dossier généré, puis activez l’extension : le bloc apparaît dans l’éditeur. L’option --variant dynamic produit un bloc dont l’affichage est calculé en PHP, comme notre shortcode : c’est la transition la plus naturelle quand on vient du PHP.

Charger scripts et styles au bon endroit

Si votre extension a besoin de CSS ou de JavaScript sur le site, ne l’écrivez pas en dur dans le HTML : déclarez-le avec wp_enqueue_style() et wp_enqueue_script() sur le hook wp_enqueue_scripts (ou admin_enqueue_scripts dans l’administration). WordPress gère alors les dépendances, la version (utile pour renouveler les caches) et, depuis WordPress 6.3, le chargement différé avec l’argument strategy.

/**
 * Charge le CSS et le JavaScript de l'extension, seulement sur les articles.
 */
function devwp_rt_enqueue_assets() {
	if ( ! is_singular( 'post' ) ) {
		return;
	}

	wp_enqueue_style(
		'devwp-reading-time',
		plugins_url( 'assets/reading-time.css', __FILE__ ),
		array(),
		'1.0.0'
	);

	wp_enqueue_script(
		'devwp-reading-time',
		plugins_url( 'assets/reading-time.js', __FILE__ ),
		array(),
		'1.0.0',
		array(
			'in_footer' => true,
			'strategy'  => 'defer',
		)
	);
}
add_action( 'wp_enqueue_scripts', 'devwp_rt_enqueue_assets' );

La condition en tête de fonction évite de charger ces fichiers sur les pages qui n’en ont pas besoin. Les autres réglages (enregistrement préalable, dépendances, chargement conditionnel) sont détaillés dans mon article sur wp_enqueue_script et wp_register_script.

Activation, désactivation et désinstallation

Trois moments de la vie d’une extension méritent leur propre code :

  • register_activation_hook() s’exécute à l’activation : c’est le moment de créer une option par défaut ou une table ;
  • register_deactivation_hook() s’exécute à la désactivation : on y arrête les tâches planifiées, mais on ne supprime pas les données, car l’utilisateur peut réactiver l’extension ;
  • le fichier uninstall.php s’exécute à la suppression définitive : c’est là, et seulement là, qu’on efface options et tables.
<?php
/**
 * Fichier uninstall.php : exécuté seulement quand l'extension est supprimée
 * depuis l'administration, jamais à la simple désactivation.
 */
defined( 'WP_UNINSTALL_PLUGIN' ) || exit;

delete_option( 'devwp_rt_wpm' );

Organiser le code quand l’extension grandit

Un fichier unique suffit pour quelques fonctions. Au-delà, découpez le code en classes rangées dans includes/, avec un espace de noms PHP et l’autoload de Composer, et séparez ce qui concerne l’administration de ce qui s’affiche sur le site. Pour structurer ces classes, il est utile d’appliquer les principes SOLID à une extension.

Des squelettes existent pour démarrer, comme le WordPress Plugin Boilerplate. Il montre une organisation possible, mais sa branche principale n’a plus évolué depuis 2019 : prenez-le comme un point de départ à adapter, pas comme une référence.

Si votre extension doit échanger des données avec une application externe, l’API REST de WordPress s’étend avec register_rest_route() ; c’est elle qui permet, par exemple, d’utiliser WordPress en headless avec Next.js. Chaque route doit déclarer un permission_callback, même quand elle est publique.

Sécuriser son plugin dès la première ligne

Les failles les plus courantes des extensions WordPress (XSS, injection SQL, falsification de requête, droits non vérifiés) se préviennent avec quatre réflexes, que WordPress facilite par ses propres fonctions de sécurité :

  • Valider et assainir les entrées : sanitize_text_field(), sanitize_email(), absint(), après wp_unslash() sur les données venues d’un formulaire ou d’une URL ;
  • Échapper les sorties, au dernier moment : esc_html(), esc_attr(), esc_url(), ou wp_kses_post() pour du HTML autorisé ;
  • Vérifier l’intention avec un nonce : wp_nonce_field() dans le formulaire, check_admin_referer() ou wp_verify_nonce() au traitement ;
  • Vérifier les droits avec current_user_can() : un nonce prouve que la demande vient de votre formulaire, pas que l’utilisateur a le droit de la faire.

Voici ces quatre réflexes réunis dans le traitement d’un formulaire d’administration. Le formulaire est envoyé vers admin-post.php, avec un champ caché action valant devwp_rt_save et le champ créé par wp_nonce_field( 'devwp_rt_save', 'devwp_rt_nonce' ) :

/**
 * Traite le formulaire de réglages envoyé vers admin-post.php.
 */
function devwp_rt_save_settings() {
	// 1. Droits : seul un administrateur peut modifier ce réglage.
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'You are not allowed to change these settings.', 'devwp-reading-time' ) );
	}

	// 2. Intention : le nonce prouve que la demande vient de notre formulaire.
	check_admin_referer( 'devwp_rt_save', 'devwp_rt_nonce' );

	// 3. Entrée : on retire les barres obliques ajoutées par WordPress, puis on assainit.
	$wpm = isset( $_POST['devwp_rt_wpm'] ) ? absint( wp_unslash( $_POST['devwp_rt_wpm'] ) ) : 200;
	update_option( 'devwp_rt_wpm', max( 1, $wpm ) );

	// 4. Redirection vers une URL interne uniquement.
	wp_safe_redirect( admin_url( 'options-general.php?page=devwp-reading-time&updated=1' ) );
	exit;
}
add_action( 'admin_post_devwp_rt_save', 'devwp_rt_save_settings' );

Pour une simple page de réglages, l’API Settings de WordPress (register_setting() avec une fonction de nettoyage) gère le nonce et les droits à votre place. Pour le SQL, $wpdb->prepare() est obligatoire dès qu’une valeur variable entre dans la requête. La sécurité d’un site ne s’arrête pas au code de ses extensions : voyez aussi les bonnes pratiques de sécurité WordPress à appliquer au niveau du site.

Rendre son plugin traduisible

Même pour un site francophone, une extension traduisible ne coûte presque rien de plus et devient réutilisable (guide d’internationalisation des extensions) :

  • écrivez les textes en anglais dans le code, entourés des fonctions de traduction : __() pour retourner un texte, esc_html__() et esc_html_e() pour le retourner ou l’afficher échappé, _n() pour les pluriels, _x() pour préciser un contexte ;
  • passez toujours le Text Domain en dernier argument, sous forme de texte littéral et non de variable : les outils d’extraction lisent le code sans l’exécuter ;
  • ajoutez un commentaire translators: au-dessus de chaque texte qui contient un %s ou un %d.

L’appel à load_plugin_textdomain(), longtemps présenté comme indispensable, ne l’est plus dans la plupart des cas. Les extensions du répertoire officiel en sont dispensées depuis WordPress 4.6, et depuis WordPress 6.8, les autres aussi si elles déclarent Text Domain et Domain Path dans leur en-tête : d’où le Requires at least: 6.8 de notre exemple. En revanche, depuis WordPress 6.7, un avertissement signale toute traduction chargée avant le hook init : n’appelez pas __() directement dans le corps du fichier principal.

Pour produire les traductions, générez le modèle .pot avec WP-CLI, puis traduisez-le avec Poedit ou, depuis l’administration, avec l’extension Loco Translate :

# Depuis le dossier de l'extension
wp i18n make-pot . languages/devwp-reading-time.pot

Tester et déboguer son plugin

Activer le mode débogage en local

// Dans wp-config.php, en local uniquement.
define( 'WP_DEBUG', true );          // Signale toutes les erreurs PHP.
define( 'WP_DEBUG_LOG', true );      // Les écrit dans wp-content/debug.log.
define( 'WP_DEBUG_DISPLAY', false ); // Sans les afficher dans les pages.

Avec ces trois constantes dans wp-config.php, les erreurs et avertissements sont écrits dans wp-content/debug.log sans être affichés aux visiteurs. Ne laissez jamais l’affichage des erreurs actif sur un site en ligne : les messages révèlent des chemins de fichiers. Pour suivre l’exécution pas à pas, Xdebug s’intègre à VS Code comme à PhpStorm, et l’extension Query Monitor affiche les requêtes, les hooks et les erreurs de chaque page.

Vérifier la qualité du code

Deux outils repèrent automatiquement l’essentiel des erreurs, avant toute relecture humaine :

  • PHP_CodeSniffer avec les WordPress Coding Standards contrôle le style, mais aussi les sorties non échappées, les nonces manquants et les fonctions déconseillées. Voici comment configurer PHPCS et les WordPress Coding Standards dans VS Code ou PhpStorm.
  • Plugin Check, l’extension de l’équipe de WordPress.org, applique les contrôles exigés pour le répertoire officiel. Elle s’utilise depuis l’administration ou en ligne de commande avec WP-CLI.

Automatiser les tests

Les tests unitaires avec PHPUnit vérifient qu’une fonction renvoie toujours le résultat attendu : par exemple, que le temps de lecture vaut 2 minutes pour 300 mots à 200 mots par minute. WP-CLI prépare l’ossature de ces tests et sa configuration d’intégration continue :

# Contrôles de l'équipe WordPress.org (extension Plugin Check active)
wp plugin check devwp-reading-time

# Ossature des tests PHPUnit et workflow GitHub Actions
wp scaffold plugin-tests devwp-reading-time --ci=github

La seconde commande crée la configuration de PHPUnit et de PHPCS, un script d’installation de la suite de tests de WordPress, un premier test d’exemple et un workflow GitHub Actions. Vos tests tournent alors à chaque envoi sur GitHub ; ajoutez-y PHPCS et Plugin Check, et faites-les tourner sur plusieurs versions de PHP ainsi que sur la dernière version de WordPress, aujourd’hui la 7.1 (voir les nouveautés de WordPress 7.1).

Publier et maintenir son plugin

Publier sur le répertoire WordPress.org

Pour diffuser gratuitement votre extension sur WordPress.org :

  1. vérifiez qu’elle respecte les directives du répertoire : licence compatible GPL, code lisible, aucun suivi des utilisateurs sans leur consentement ;
  2. rédigez un fichier readme.txt au format standard, avec notamment Tested up to, Stable tag et Requires PHP ;
  3. activez la double authentification sur votre compte WordPress.org et faites passer Plugin Check à votre extension : les deux sont obligatoires pour toute nouvelle soumission depuis le 1er octobre 2024 ;
  4. soumettez le ZIP : le contrôle automatique est suivi d’une revue manuelle par l’équipe des extensions ;
  5. une fois l’extension acceptée, publiez ses versions avec le dépôt SVN fourni par WordPress.org.

Ou la garder privée

Une extension écrite pour un seul site n’a pas besoin du répertoire : un ZIP ou un dépôt Git privé suffit. Ajoutez alors l’en-tête Update URI: false, pour qu’aucune extension homonyme du répertoire ne soit un jour proposée en « mise à jour ».

Documenter et maintenir

Une extension diffusée est un engagement. Tenez un journal des modifications dans le readme.txt, testez l’extension avec chaque version majeure de WordPress avant de mettre à jour Tested up to, et répondez aux questions du forum de support. Une extension abandonnée dont une faille n’est pas corrigée finit fermée sur le répertoire, et reste souvent une porte d’entrée sur les sites qui l’utilisent encore.

Les ressources pour apprendre à développer un plugin WordPress

Tout ce qu’il faut pour apprendre est gratuit et en ligne, mais en anglais pour l’essentiel :

  • Plugin Handbook : le guide officiel du développement d’extensions, qui a remplacé l’ancien Codex ; commencez par « Plugin Basics » et les bonnes pratiques ;
  • Code Reference : la documentation de chaque fonction, hook et classe, avec sa version d’apparition et ses dépréciations ;
  • Block Editor Handbook : tout sur les blocs, block.json et les paquets JavaScript ;
  • Learn WordPress, en particulier le cours « Beginner WordPress Developer » : des leçons structurées sur le fonctionnement de WordPress, les outils de développement local et les concepts de base ;
  • WordPress Playground : un WordPress complet dans le navigateur, pour expérimenter sans risque.

En vidéo, la série « Create a WordPress Plugin from Scratch » d’Alessandro Castellani (alecaddd) reste une bonne introduction à la logique d’une extension orientée objet. Son premier épisode date d’août 2017 : la structure et les principes restent valables, mais les blocs, les outils JavaScript et certaines fonctions ont évolué depuis. Vérifiez chaque fonction dans la Code Reference avant de la reprendre.

Créer un plugin WordPress avec une IA

ChatGPT et les autres assistants de code produisent volontiers un squelette d’extension, et c’est un vrai gain de temps pour un premier jet. Mais un code généré n’est pas un code vérifié : sorties non échappées, nonces absents, fonctions dépréciées ou hooks qui n’existent pas font partie des erreurs typiques. Relisez chaque ligne, vérifiez chaque fonction dans la Code Reference et faites passer le résultat par PHPCS et Plugin Check. Une IA aide surtout ceux qui savent déjà juger le code qu’elle produit : c’est tout l’intérêt d’apprendre les bases présentées ici.

Par où commencer ?

Lancez wp-env ou ouvrez WordPress Playground, recopiez l’extension de temps de lecture, puis faites-la évoluer : une page de réglages pour le nombre de mots par minute, un bloc à la place du shortcode, un premier test PHPUnit. C’est en améliorant une petite extension réelle, la documentation officielle à portée de main, qu’on progresse le plus vite.

Et si votre projet demande une extension métier (connexion à une API, logique propre à votre activité, intégration à WooCommerce) que vous préférez confier à un professionnel, je peux la développer pour vous : voyez mon offre de plugin WordPress sur mesure.

Questions fréquentes sur la création d’un plugin WordPress

Oui, il faut au minimum les bases de PHP, car un plugin est un programme PHP qui s’exécute dans WordPress. Le HTML et le CSS servent pour l’affichage, et le JavaScript devient nécessaire pour créer des blocs. Sans savoir coder, on peut assembler des extensions existantes, mais pas en créer une qui soit sûre et maintenable.

Oui : WordPress, sa documentation officielle, WP-CLI, wp-env, WordPress Playground, Plugin Check et des éditeurs comme Visual Studio Code sont gratuits. La publication sur le répertoire WordPress.org est gratuite elle aussi. Le seul vrai coût est le temps passé à apprendre, à tester et à maintenir l’extension.

Oui pour un premier jet, à condition de relire et de vérifier tout le code produit. Les assistants oublient souvent l’échappement des sorties, les nonces ou la vérification des droits, et citent parfois des fonctions dépréciées ou des hooks inexistants. Passez systématiquement le résultat par PHPCS et Plugin Check avant de l’utiliser sur un site.

Tout dépend de son périmètre. Une fois les bases acquises, un plugin minimal comme celui de ce guide s’écrit en une séance de travail. Une extension métier, avec page de réglages, connexion à une API, traductions et tests, demande un vrai cadrage avant de pouvoir être estimée.

Dans un plugin dès que le code apporte une fonctionnalité qui doit survivre à un changement de thème : type de contenu, shortcode, réglage, connexion à un service. Le fichier functions.php d’un thème enfant convient seulement au code lié à l’apparence, car il disparaît avec le thème.

Copiez son dossier dans wp-content/plugins/, ou compressez-le en ZIP et téléversez-le depuis Extensions > Ajouter une extension > Téléverser une extension, puis activez-le. Faites-le d’abord sur un site local ou de préproduction, avec le mode débogage actif, avant de l’installer sur le site en ligne.

Mis à jour en octobre 2026 par un développeur WordPress freelance senior.

Faites tourner cet article !

À propos de l'auteur : Développeur WordPress freelance

Développeur WordPress freelance
Développeur WordPress Full Stack avec 14 ans d’expérience, j’accompagne les agences et les entreprises dans la création, la refonte et l’optimisation de leurs sites WordPress et boutiques WooCommerce. Développement sur mesure, maintenance, sécurité ou dépannage : je mets mon expertise au service de sites performants, fiables et adaptés à vos objectifs.