Créer un plugin WordPress personnalisé : guide complet

Créer un plugin WordPress personnalisé consiste à placer une fonctionnalité dans une extension autonome, puis à utiliser les hooks du CMS. Vous conservez ainsi votre code lors d’un changement de thème, avec des réglages contrôlés et un affichage adapté à votre projet.

Vous avez ajouté quelques fonctions dans un thème enfant. Puis un autre projet arrive, avec ses propres réglages, ses exceptions et ses correctifs. Progressivement, le fichier devient un tiroir dont vous préférez ne plus ouvrir le fond. Il existe une solution plus lisible : créer une petite extension dédiée.

Dans ce tutoriel, nous allons construire Sky Notice, un plugin qui affiche un encadré personnalisable. Son administration permet de modifier un titre, un message et un bouton facultatif. Ensuite, un shortcode place cet encadré exactement où vous le souhaitez. L’extension n’insère rien automatiquement et ne charge aucun JavaScript.

Les exemples ciblent PHP 8.3 ou supérieur et WordPress 6.6 ou supérieur. Vous pourrez recopier tous les fichiers présentés, puis installer votre archive ZIP depuis l’administration. Nous utiliserons les API natives : les options, la Settings API, les shortcodes et le chargement des ressources.

Plugin, MU-plugin, snippet ou functions.php : que choisir ?

Commencez par définir la responsabilité du code. Une fonctionnalité métier devrait survivre à une refonte graphique. En revanche, un ajustement propre au rendu d’un thème peut rester dans ce thème, idéalement dans un thème enfant lorsque vous personnalisez un produit tiers.

Ainsi, un filtre qui adapte une règle commerciale appartient généralement à une extension. Une modification de la structure d’un modèle PHP relève plutôt du thème. Cette distinction complète notre tutoriel pour créer un thème WordPress personnalisé sans constructeur de pages.

SolutionUsage adaptéPoint à connaître
Plugin personnaliséFonctionnalité autonome, réglages, intégrationsActivation et désactivation depuis les extensions
MU-pluginComportement que l’administration ordinaire ne doit pas désactiverChargement automatique ; cycle d’activation différent
Gestionnaire de snippetsPetite adaptation ciblée, facile à organiserLe code dépend du gestionnaire et de sa configuration
functions.phpFonctionnalités liées au thème actifLe comportement disparaît lorsque ce thème change

Un MU-plugin ne constitue donc pas simplement un plugin normal déplacé dans un autre dossier. WordPress ne parcourt pas automatiquement tous ses sous-dossiers et n’exécute pas les hooks d’activation habituels. Pour notre exemple administrable, une extension classique offre un point de départ plus clair.

Par ailleurs, créer un plugin ne signifie pas reconstruire une fonctionnalité mature déjà disponible. Définissez le besoin, comparez les solutions existantes, puis développez lorsque cette approche apporte un avantage concret. Ici, notre objectif reste pédagogique : comprendre une extension complète, dont chaque fichier garde un rôle identifiable.

Distingo propose un taux d'intérêt de 4,5 % pendant 3 mois, plus 80 euros, jusqu'au 30 octobre 2026

Ce que notre extension fera réellement

Sky Notice conserve une configuration commune à l’ensemble du site. Vous pourrez changer son titre, son message, le texte du bouton et son URL. Ensuite, vous afficherez cette configuration avec le shortcode [sky_notice], dans un article ou une page.

Vous pourrez également remplacer le titre pour une occurrence précise. Le message et le bouton resteront communs. Ainsi, modifier le réglage principal mettra à jour toutes les occurrences qui l’utilisent. Cette logique diffère d’une composition Gutenberg non synchronisée, dont chaque copie peut évoluer indépendamment.

Nous accepterons uniquement du texte simple dans le message. Les retours à la ligne fonctionneront, tandis que les balises HTML seront retirées. Cette décision simplifie le formulaire, la validation et les tests. Si votre besoin exige des listes ou des images, choisissez plutôt des blocs ou définissez explicitement le HTML autorisé.

Enfin, le bouton restera facultatif. Il apparaîtra seulement lorsque son libellé et son URL seront renseignés. Une configuration sans titre ou sans message ne produira aucun encadré. Nous évitons ainsi les cartes vides et les liens sans destination.

1. Préparer l’environnement et l’arborescence

Travaillez sur une installation locale ou une préproduction. Vous pourrez provoquer une erreur PHP, corriger un chemin ou désactiver votre extension sans gêner les visiteurs. Notre comparatif des environnements de développement WordPress présente plusieurs points de départ.

Dans wp-content/plugins/, créez un dossier sky-notice. Respectez ensuite cette organisation :

sky-notice/
├── sky-notice.php
├── includes/
│   ├── settings.php
│   └── frontend.php
├── assets/css/notice.css
├── languages/
├── uninstall.php
└── readme.txt

Le fichier principal identifie l’extension et charge ses composants. Ensuite, settings.php gère les réglages, tandis que frontend.php construit l’affichage. Cette séparation suffit pour notre périmètre. Ajouter une architecture complexe avant d’avoir une fonctionnalité ne rendrait pas l’exemple plus professionnel.

Versionnez également le dossier. Vous pourrez comparer vos modifications et retrouver une version fonctionnelle. Le guide pour versionner du code avec Git et GitHub complète ce workflow. Enfin, excluez du dépôt les identifiants, les exports de base et les fichiers temporaires.

2. Créer le fichier principal du plugin

Placez le contenu suivant dans sky-notice/sky-notice.php :

<?php
/**
 * Plugin Name:       Sky Notice
 * Plugin URI:        https://www.skyminds.net/creer-plugin-wordpress-personnalise/
 * Description:       Un encadré configurable, affiché uniquement avec le shortcode [sky_notice].
 * Version:           1.0.0
 * Requires at least: 6.6
 * Requires PHP:      8.3
 * Author:            Matt Biscay
 * Author URI:        https://www.skyminds.net/
 * License:          GPL-2.0-or-later
 * License URI:      https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:      sky-notice
 * Domain Path:      /languages
 *
 * @package Sky_Notice
 */

defined( 'ABSPATH' ) || exit;

define( 'SKY_NOTICE_VERSION', '1.0.0' );
define( 'SKY_NOTICE_FILE', __FILE__ );

require_once __DIR__ . '/includes/settings.php';
require_once __DIR__ . '/includes/frontend.php';

/**
 * Create site-local defaults without overwriting existing settings.
 *
 * @param bool $network_wide Whether network activation was requested.
 * @return void
 */
function sky_notice_activate( bool $network_wide = false ): void {
	if ( $network_wide ) {
		wp_die( esc_html__( 'Sky Notice doit être activé individuellement sur chaque site.', 'sky-notice' ) );
	}

	add_option( 'sky_notice_settings', sky_notice_defaults(), '', false );
}
register_activation_hook( __FILE__, 'sky_notice_activate' );

/**
 * Register translations for a privately distributed plugin.
 *
 * @return void
 */
function sky_notice_load_textdomain(): void {
	load_plugin_textdomain( 'sky-notice', false, dirname( plugin_basename( SKY_NOTICE_FILE ) ) . '/languages' );
}
add_action( 'init', 'sky_notice_load_textdomain', 5 );Langage du code : HTML, XML (xml)

L’en-tête contient notamment Plugin Name, la version et les exigences techniques. WordPress utilise ces informations pour présenter l’extension. Ensuite, ABSPATH empêche l’exécution directe du fichier, tandis que require_once charge chaque composant une seule fois.

Le préfixe sky_notice_ distingue nos fonctions des autres extensions. De leur côté, les constantes centralisent la version et le chemin du fichier principal. La version servira aussi à renouveler l’URL de la feuille CSS après une modification.

Le hook d’activation crée l’option initiale avec add_option(). Cette fonction conserve une éventuelle configuration existante. De plus, son dernier argument désactive l’autoload : notre petit réglage n’a pas besoin d’être chargé automatiquement sur toutes les requêtes. Nous le lirons lorsque la fonctionnalité en aura besoin.

L’activation réseau est volontairement refusée. Cette base utilise des réglages propres à chaque site et ne fournit pas une administration réseau complète. En multisite, activez-la individuellement. Nous préciserons également les limites de son nettoyage lors de la désinstallation.

Si WordPress ne détecte pas votre extension, consultez le guide sur les plugins absents de la liste des extensions. Un dossier imbriqué ou un en-tête oublié suffit souvent à expliquer le problème.

Distingo propose un taux d'intérêt de 4,5 % pendant 3 mois, plus 80 euros, jusqu'au 30 octobre 2026

3. Définir les réglages et leur validation

Créez maintenant includes/settings.php avec le fichier complet ci-dessous. Il réunit les valeurs initiales, le nettoyage des données, l’enregistrement du réglage et le formulaire d’administration :

<?php
/**
 * Site settings and administration form.
 *
 * @package Sky_Notice
 */

defined( 'ABSPATH' ) || exit;

/**
 * Return the initial notice configuration.
 *
 * @return array<string, string|bool> Default settings.
 */
function sky_notice_defaults(): array {
	return array(
		'title'               => __( 'Une information utile', 'sky-notice' ),
		'message'             => __( 'Personnalisez cet encadré dans Réglages → Sky Notice.', 'sky-notice' ),
		'button_label'        => __( 'En savoir plus', 'sky-notice' ),
		'button_url'          => '',
		'delete_on_uninstall' => false,
	);
}

/**
 * Normalize known settings and discard unsupported values.
 *
 * @param mixed $input Submitted or stored settings.
 * @return array<string, string|bool> Sanitized settings.
 */
function sky_notice_sanitize_settings( mixed $input ): array {
	$input = is_array( $input ) ? $input : array();
	$text  = static fn( string $key ): string => is_string( $input[ $key ] ?? null ) ? $input[ $key ] : '';
	$url   = esc_url_raw( $text( 'button_url' ), array( 'http', 'https' ) );

	if ( ! in_array( wp_parse_url( $url, PHP_URL_SCHEME ), array( 'http', 'https' ), true )
		|| ! wp_parse_url( $url, PHP_URL_HOST ) ) {
		$url = '';
	}

	return array(
		'title'               => sanitize_text_field( $text( 'title' ) ),
		'message'             => sanitize_textarea_field( $text( 'message' ) ),
		'button_label'        => sanitize_text_field( $text( 'button_label' ) ),
		'button_url'          => $url,
		'delete_on_uninstall' => in_array( $input['delete_on_uninstall'] ?? false, array( true, 1, '1' ), true ),
	);
}

/**
 * Read settings defensively, including missing or malformed options.
 *
 * @return array<string, string|bool> Effective settings.
 */
function sky_notice_get_settings(): array {
	$stored = get_option( 'sky_notice_settings', array() );

	return sky_notice_sanitize_settings(
		array_merge( sky_notice_defaults(), is_array( $stored ) ? $stored : array() )
	);
}

/**
 * Register the option and its sanitizer with the Settings API.
 *
 * @return void
 */
function sky_notice_register_settings(): void {
	register_setting(
		'sky_notice',
		'sky_notice_settings',
		array(
			'type'              => 'array',
			'sanitize_callback' => 'sky_notice_sanitize_settings',
			'default'           => sky_notice_defaults(),
			'show_in_rest'      => false,
		)
	);
}
add_action( 'admin_init', 'sky_notice_register_settings' );

/**
 * Add the settings page to the standard WordPress settings menu.
 *
 * @return void
 */
function sky_notice_add_settings_page(): void {
	add_options_page( 'Sky Notice', 'Sky Notice', 'manage_options', 'sky-notice', 'sky_notice_render_settings_page' );
}
add_action( 'admin_menu', 'sky_notice_add_settings_page' );

/**
 * Render the protected settings form using WordPress administration styles.
 *
 * @return void
 */
function sky_notice_render_settings_page(): void {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'Vous ne pouvez pas modifier ces réglages.', 'sky-notice' ) );
	}

	$settings = sky_notice_get_settings();
	$fields   = array(
		'title'        => __( 'Titre', 'sky-notice' ),
		'message'      => __( 'Message', 'sky-notice' ),
		'button_label' => __( 'Texte du bouton', 'sky-notice' ),
		'button_url'   => __( 'URL du bouton', 'sky-notice' ),
	);
	?>
	<div class="wrap">
		<h1>Sky Notice</h1>
		<p><?php esc_html_e( 'Insérez [sky_notice] dans un bloc Code court. Le bouton nécessite un texte et une URL HTTP(S) absolue.', 'sky-notice' ); ?></p>
		<?php settings_errors( 'sky_notice_settings' ); ?>
		<form method="post" action="options.php">
			<?php settings_fields( 'sky_notice' ); ?>
			<table class="form-table" role="presentation">
				<?php foreach ( $fields as $key => $label ) : ?>
					<tr>
						<th scope="row"><label for="sky-notice-<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label></th>
						<td>
							<?php if ( 'message' === $key ) : ?>
								<textarea class="large-text" rows="5" id="sky-notice-message" name="sky_notice_settings[message]"><?php echo esc_textarea( $settings['message'] ); ?></textarea>
							<?php else : ?>
								<input class="regular-text" type="<?php echo 'button_url' === $key ? 'url' : 'text'; ?>" id="sky-notice-<?php echo esc_attr( $key ); ?>" name="sky_notice_settings[<?php echo esc_attr( $key ); ?>]" value="<?php echo esc_attr( $settings[ $key ] ); ?>">
							<?php endif; ?>
						</td>
					</tr>
				<?php endforeach; ?>
				<tr>
					<th scope="row"><?php esc_html_e( 'Désinstallation', 'sky-notice' ); ?></th>
					<td><label><input type="checkbox" name="sky_notice_settings[delete_on_uninstall]" value="1" <?php checked( $settings['delete_on_uninstall'] ); ?>> <?php esc_html_e( 'Supprimer les réglages lors de la suppression de l’extension.', 'sky-notice' ); ?></label></td>
				</tr>
			</table>
			<?php submit_button(); ?>
		</form>
	</div>
	<?php
}Langage du code : JavaScript (javascript)

Prenons le temps de comprendre ce fichier. D’abord, sky_notice_defaults() décrit la configuration initiale. Ensuite, sky_notice_sanitize_settings() accepte une entrée quelconque et produit un tableau limité aux clés prévues. Une valeur inattendue ne doit pas devenir une erreur de type ou un réglage supplémentaire.

Les champs courts passent par sanitize_text_field(). Le message utilise sanitize_textarea_field(), qui conserve ses retours à la ligne. De son côté, l’URL passe par esc_url_raw(), puis par un contrôle de son protocole et de son hôte. Nous acceptons uniquement des liens HTTP ou HTTPS absolus.

Ainsi, javascript:alert(1), une URL FTP ou un chemin relatif ne produiront pas de bouton. Cette règle évite les interprétations ambiguës. Toutefois, elle ne vérifie pas que la page distante existe : le plugin ne lance aucune requête réseau pour contrôler un lien.

Le champ de suppression mérite aussi une validation stricte. Nous reconnaissons seulement true, 1 et la chaîne 1. Une chaîne quelconque ou un tableau ne doit pas activer un nettoyage de données. Enfin, toutes les clés inconnues disparaissent du résultat.

À la lecture, sky_notice_get_settings() complète les valeurs manquantes, puis normalise à nouveau le tableau. Cette protection reste utile lorsque les données proviennent d’une ancienne version, d’une commande WP-CLI ou d’une autre intégration. Elle ne remplace pas l’échappement au moment de l’affichage.

4. Comprendre la Settings API et les permissions

Notre formulaire utilise register_setting() sur admin_init. Cette déclaration associe l’option sky_notice_settings au groupe sky_notice, avec son callback de nettoyage. La documentation de register_setting() détaille les arguments disponibles.

Ensuite, add_options_page() place l’interface sous Réglages → Sky Notice. La capacité manage_options protège son accès. Nous contrôlons également cette capacité dans le callback d’affichage. Masquer un menu ne suffit pas à autoriser ou interdire une opération.

Le formulaire envoie ses données vers options.php. Surtout, settings_fields( 'sky_notice' ) ajoute les champs attendus par WordPress et le nonce du groupe. Nous utilisons donc le circuit de sauvegarde natif, avec ses contrôles de permissions et de requête. Il n’est pas nécessaire d’écrire un traitement manuel dans $_POST.

Gardez néanmoins les rôles de chaque mécanisme en tête. Le nonce aide à contrôler l’origine d’une requête ; il n’accorde pas une permission. Le nettoyage prépare les données ; il ne remplace pas leur échappement. Enfin, type => array décrit le réglage, mais notre callback garantit réellement sa structure dans ce formulaire classique.

Les réglages ne sont pas exposés dans la REST API : show_in_rest reste désactivé. Si vous construisez plus tard une interface JavaScript, définissez d’abord son schéma et ses permissions. Ouvrir une option à la REST API uniquement pour faciliter un formulaire constituerait ici un détour inutile.

5. Écrire le shortcode et les règles de chargement

Ajoutez maintenant includes/frontend.php :

<?php
/**
 * Shortcode output and conditional frontend styles.
 *
 * @package Sky_Notice
 */

defined( 'ABSPATH' ) || exit;

/**
 * Register the shortcode after WordPress initialization.
 *
 * @return void
 */
function sky_notice_register_shortcode(): void {
	add_shortcode( 'sky_notice', 'sky_notice_shortcode' );
}
add_action( 'init', 'sky_notice_register_shortcode' );

/**
 * Return escaped notice markup without printing it.
 *
 * @param array|string $atts Shortcode attributes, or an empty string.
 * @return string Accessible notice markup, or an empty string.
 */
function sky_notice_shortcode( array|string $atts = array() ): string {
	$settings = sky_notice_get_settings();
	$atts     = shortcode_atts( array( 'title' => $settings['title'] ), is_array( $atts ) ? $atts : array(), 'sky_notice' );
	$title    = sanitize_text_field( is_string( $atts['title'] ) ? $atts['title'] : '' );

	if ( '' === trim( $title ) || '' === trim( $settings['message'] ) ) {
		return '';
	}

	$title_id = wp_unique_id( 'sky-notice-title-' );
	$button   = '';

	if ( '' !== $settings['button_url'] && '' !== trim( $settings['button_label'] ) ) {
		$button = sprintf(
			'<a class="sky-notice__button" href="%1$s">%2$s</a>',
			esc_url( $settings['button_url'] ),
			esc_html( $settings['button_label'] )
		);
	}

	return sprintf(
		'<aside class="sky-notice" aria-labelledby="%1$s"><p class="sky-notice__title" id="%1$s">%2$s</p><p class="sky-notice__message">%3$s</p>%4$s</aside>',
		esc_attr( $title_id ),
		esc_html( $title ),
		nl2br( esc_html( $settings['message'] ) ),
		$button
	);
}

/**
 * Enqueue CSS before the head only when the main content needs it.
 *
 * @return void
 */
function sky_notice_enqueue_assets(): void {
	if ( is_admin() || is_feed() ) {
		return;
	}

	$post   = get_queried_object();
	$needed = is_singular() && $post instanceof WP_Post
		&& ! post_password_required( $post )
		&& has_shortcode( $post->post_content, 'sky_notice' );

	/**
	 * Extend detection for a template, widget or reusable pattern.
	 *
	 * @param bool $needed Whether the current request needs notice styles.
	 */
	if ( ! apply_filters( 'sky_notice_load_styles', $needed ) ) {
		return;
	}

	wp_enqueue_style( 'sky-notice', plugins_url( 'assets/css/notice.css', SKY_NOTICE_FILE ), array(), SKY_NOTICE_VERSION );
}
add_action( 'wp_enqueue_scripts', 'sky_notice_enqueue_assets' );Langage du code : HTML, XML (xml)

Le premier hook enregistre le shortcode sur init. Ensuite, WordPress appelle notre callback lorsqu’il rencontre sa balise. Ce callback retourne une chaîne : il n’imprime pas directement l’encadré avec echo. Cette distinction permet au CMS d’insérer le résultat au bon endroit.

shortcode_atts() définit l’attribut accepté, ici title. Puis nous normalisons sa valeur avant de construire le HTML. La documentation des shortcodes avec paramètres explique ce mécanisme. Pour notre première version, les visiteurs ne peuvent modifier ni l’URL ni le message par cet attribut.

Chaque valeur rejoint ensuite la fonction d’échappement adaptée : esc_html() pour le texte, esc_attr() pour l’identifiant et esc_url() pour le lien. Pour le message, nous échappons d’abord le texte, puis nl2br() ajoute les retours à la ligne. Les seuls éléments HTML supplémentaires viennent ainsi de notre code.

L’encadré utilise un élément aside, avec un titre associé par aria-labelledby. De plus, wp_unique_id() évite de dupliquer cet identifiant lorsque deux encadrés apparaissent sur la même page. Nous gardons le titre dans un paragraphe afin de ne pas imposer un niveau de titre aux contenus qui utilisent le shortcode.

Enfin, le hook wp_enqueue_scripts prépare la CSS avant l’affichage du contenu. Le chargement dépend de la requête, de l’accès au contenu et de la présence du shortcode. Cette détection vise les articles et les pages individuels. Elle ne parcourt pas toute une archive et ne lance pas une nouvelle recherche en base.

Kinsta: Premium Managed WordPress hosting

6. Ajouter une CSS moderne et isolée

Créez assets/css/notice.css :

.sky-notice {
	--notice-accent: #176b57;
	margin-block: 2rem;
	padding: clamp(1.25rem, 3vw, 2rem);
	border: 1px solid #b9dfd1;
	border-inline-start: 5px solid var(--notice-accent);
	border-radius: 1rem;
	color: #17231f;
	background: #f3faf7;
}

.sky-notice .sky-notice__title {
	margin: 0 0 0.75rem;
	color: #17231f;
	font-size: clamp(1.2rem, 2vw, 1.5rem);
	font-weight: 750;
	line-height: 1.3;
}

.sky-notice .sky-notice__message {
	margin: 0;
	color: #42564f;
	overflow-wrap: anywhere;
}

.sky-notice .sky-notice__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-block-size: 3rem;
	max-inline-size: 100%;
	margin-block-start: 1.25rem;
	padding: 0.75rem 1.25rem;
	border: 2px solid var(--notice-accent);
	border-radius: 0.625rem;
	color: #fff;
	background: var(--notice-accent);
	font-weight: 700;
	text-align: center;
	text-decoration: none;
	overflow-wrap: anywhere;
}

.sky-notice .sky-notice__button:hover {
	border-color: #105141;
	color: #fff;
	background: #105141;
}

.sky-notice .sky-notice__button:focus-visible {
	outline: 3px solid #105141;
	outline-offset: 4px;
}Langage du code : CSS (css)

Toutes les règles partent de .sky-notice. Ainsi, l’extension limite ses interactions avec les paragraphes, les liens et les boutons du thème. Elle utilise les polices déjà présentes et ne télécharge aucune ressource externe.

Les propriétés logiques, comme margin-block et border-inline-start, rendent la mise en page moins dépendante du sens de lecture. De son côté, clamp() adapte les espacements sans multiplier les points de rupture. Enfin, le focus visible permet de repérer le bouton pendant une navigation au clavier.

Cette feuille reste volontairement indépendante du style CTA de SkyMinds. Les CTA commerciaux de cet article reprennent notre modèle éditorial commun. En revanche, le plugin téléchargeable doit fonctionner sur votre propre site, même lorsque votre thème ne connaît aucune classe SkyMinds.

7. Utiliser et tester l’encadré dans Gutenberg

Vous pouvez maintenant activer Sky Notice. Ensuite, ouvrez Réglages → Sky Notice, personnalisez les champs et enregistrez. Ajoutez un bloc Code court dans une page, puis saisissez :

[sky_notice]Langage du code : JSON / JSON avec commentaires (json)

Pour modifier uniquement son titre à cet emplacement, utilisez :

[sky_notice title="Besoin d’un accompagnement ?"]Langage du code : JSON / JSON avec commentaires (json)

Prévisualisez ensuite la page publique. Le bloc Code court ne fournit pas forcément une représentation fidèle de la carte dans l’éditeur. Par ailleurs, un bloc Code sert à afficher du code : il ne remplace pas le bloc Code court destiné à exécuter notre balise.

Essayez également deux occurrences dans la même page. Les textes communs doivent correspondre aux réglages, tandis que les identifiants restent distincts. Puis retirez l’URL du bouton : le lien doit disparaître. Enfin, videz le message et vérifiez que l’extension ne produit plus d’encadré.

Pour une validation technique, soumettez aussi du HTML dans les champs et une URL au protocole interdit. Le formulaire ne doit pas conserver de balises exécutables, tandis que l’affichage doit rester correctement échappé. Tester uniquement un titre sage et un lien valide laisse beaucoup de portes fermées… mais aucune certitude sur leur serrure.

8. Charger les ressources uniquement au bon endroit

Notre détection repose sur has_shortcode() dans le contenu principal. Cette méthode convient au périmètre annoncé. Cependant, une composition synchronisée peut stocker sa balise dans un autre contenu. De même, un widget ou un modèle peut l’ajouter après la préparation de l’en-tête.

Dans ces cas, le shortcode pourra produire son HTML sans que notre détection ait chargé sa CSS. Utilisez alors le filtre prévu pour déclarer précisément les requêtes concernées. Par exemple, pour une page connue :

/**
 * Load notice styles on the page whose template renders the shortcode.
 *
 * @param bool $needed Whether styles are already required.
 * @return bool Whether to load the stylesheet.
 */
function mysite_load_notice_styles( bool $needed ): bool {
	return $needed || is_page( 123 );
}
add_filter( 'sky_notice_load_styles', 'mysite_load_notice_styles' );Langage du code : PHP (php)

Remplacez 123 par l’identifiant réel de la page. Placez cette adaptation dans une extension propre au site, ou dans le code que vous maintenez pour cette intégration. Le guide pour récupérer un identifiant WordPress vous aidera à retrouver le bon objet.

Vous pourriez charger systématiquement la petite feuille CSS. Ce choix simplifierait certains usages, mais il ne répondrait plus à notre objectif de chargement conditionnel. Définissez donc le périmètre avant de choisir votre stratégie. La détection universelle de toutes les sources de contenu mérite un développement séparé.

Enfin, contrôlez les ressources dans les outils réseau du navigateur. Une page sans shortcode ne doit pas demander notice.css. Après une modification de la feuille, augmentez SKY_NOTICE_VERSION, puis contrôlez vos caches. Notre guide pour alléger WordPress et ses ressources approfondit cette démarche.

Distingo propose un taux d'intérêt de 4,5 % pendant 3 mois, plus 80 euros, jusqu'au 30 octobre 2026

9. Préparer la désactivation et la désinstallation

Désactiver une extension et la supprimer répondent à deux besoins différents. La désactivation arrête son comportement. Elle ne devrait pas effacer automatiquement vos réglages. Vous pourriez simplement tester une incompatibilité ou préparer une mise à jour.

Notre extension ne crée ni tâche planifiée, ni règle de réécriture, ni ressource temporaire à retirer. Un hook de désactivation vide n’apporterait donc rien. En revanche, la suppression complète peut nécessiter un nettoyage volontaire. Ajoutez ce fichier uninstall.php à la racine du plugin :

<?php
/**
 * Remove site-local settings only after an explicit opt-in.
 *
 * @package Sky_Notice
 */

defined( 'WP_UNINSTALL_PLUGIN' ) || exit;

// Settings belong to each site. Network-wide data cleanup is out of scope.
if ( is_multisite() ) {
	return;
}

$sky_notice_settings = get_option( 'sky_notice_settings', array() );

if ( is_array( $sky_notice_settings )
	&& in_array( $sky_notice_settings['delete_on_uninstall'] ?? false, array( true, 1, '1' ), true ) ) {
	delete_option( 'sky_notice_settings' );
}Langage du code : HTML, XML (xml)

WordPress exécute ce fichier pendant la désinstallation. La constante WP_UNINSTALL_PLUGIN vérifie ce contexte. Ensuite, notre code efface l’option seulement lorsque l’administrateur a coché la case correspondante. Une désactivation ordinaire conserve donc toujours les réglages.

Cette première version ne purge pas les données d’un réseau multisite. Le fichier quitte explicitement ce contexte afin de ne pas prétendre nettoyer tous les sites en traitant uniquement le site courant. Une extension distribuée pour le multisite devra définir son propre cycle de déploiement, de stockage et de suppression.

Enfin, la suppression du plugin ne retire pas ses shortcodes des articles. Une balise peut rester visible lorsque son callback n’existe plus. Avant une désinstallation définitive, recherchez ses usages et remplacez-les si nécessaire. Le cycle de vie d’une extension comprend aussi les contenus qu’elle a permis de rédiger.

10. Ajouter les traductions et préparer l’archive ZIP

Toutes les chaînes d’interface utilisent le domaine sky-notice. Notre chargement sur init convient à cette extension distribuée sous forme d’archive privée. Ensuite, vous pourrez générer un fichier POT et créer les traductions nécessaires. Le tutoriel sur Poedit et les traductions WordPress détaille ce workflow.

wp i18n make-pot wp-content/plugins/sky-notice \
  wp-content/plugins/sky-notice/languages/sky-notice.pot

Ajoutez également un fichier readme.txt qui explique l’installation, le shortcode et les limites. Puis archivez le dossier sky-notice, avec ses fichiers à l’intérieur. Une archive contenant plusieurs niveaux de dossiers peut compliquer la détection du fichier principal.

N’incluez pas vos identifiants, votre installation WordPress locale ou vos outils de test dans cette archive. Elle doit contenir uniquement l’extension distribuable. Ensuite, installez-la dans une seconde installation de test via Extensions → Ajouter → Téléverser une extension. Ce dernier passage vérifie le paquet que recevra réellement votre lecteur.

L’archive fournie avec ce tutoriel contient la version complète 1.0.0. Vous pouvez aussi reconstruire intégralement l’extension avec les fichiers présentés ci-dessus. Avant un usage client, adaptez ses textes, son style et son périmètre fonctionnel.

11. Vérifier le plugin avant de le livrer

Commencez par contrôler la syntaxe de chaque fichier PHP. Ensuite, utilisez PHP_CodeSniffer avec WordPress Coding Standards pour repérer les écarts de conventions. Ces outils complètent les essais fonctionnels : ils ne vérifient pas, à eux seuls, le bon fonctionnement du formulaire et du shortcode.

find wp-content/plugins/sky-notice -type f -name '*.php' -exec php -l {} \;
phpcs --standard=WordPress wp-content/plugins/sky-noticeLangage du code : JavaScript (javascript)

Vérifiez ensuite les scénarios qui correspondent aux promesses du plugin : enregistrement des réglages, entrée mal formée, accès non autorisé, titre personnalisé, message vide, bouton incomplet et plusieurs encadrés. Puis contrôlez le clavier, le zoom et les petits écrans.

Testez également le cycle de vie. Désactivez puis réactivez l’extension : les réglages doivent rester présents. Sur une copie jetable du site, vérifiez ensuite les deux choix de désinstallation. Le nettoyage des données mérite un test explicite, surtout lorsque l’interface propose de le rendre facultatif.

Enfin, documentez la configuration vérifiée : version WordPress, version PHP, thème et extensions importantes. Pour préparer d’autres environnements, consultez le guide sur la compatibilité WordPress avec PHP. Un plugin maintenable comprend aussi une manière reproductible de le vérifier.

Dépannage : les problèmes les plus fréquents

SymptômePremière vérification
Le plugin n’apparaît pasEn-tête, emplacement et structure du ZIP
Une erreur PHP apparaîtSyntaxe, version PHP et chemins des fichiers inclus
La page de réglages reste inaccessibleCapacité manage_options du compte utilisé
Le shortcode s’affiche comme du texteExtension active et bloc Code court utilisé
L’encadré reste absentPrésence du titre et du message
Le bouton disparaîtLibellé et URL absolue HTTP(S) valides
Le style manque dans un widget ou une compositionDétection à étendre avec sky_notice_load_styles
Les anciens réglages persistent après suppressionConservation choisie ou contexte multisite

Si le rendu conserve une ancienne version, vérifiez aussi les caches du site et du navigateur. Toutefois, ne videz pas tous les caches pour masquer un mauvais chemin de fichier. Identifiez d’abord la ressource réellement demandée et son statut HTTP.

FAQ : créer son plugin WordPress

Faut-il maîtriser la programmation orientée objet ?

Non. Une extension limitée peut utiliser des fonctions préfixées et des fichiers clairement séparés. Les classes deviennent utiles lorsque leur organisation répond à une complexité réelle. Elles ne constituent pas un passage obligé pour comprendre les hooks et les API WordPress.

Un plugin personnalisé ralentit-il forcément WordPress ?

Non. Son coût dépend du travail exécuté : requêtes, calculs, appels réseau et ressources publiques. Sky Notice ne charge aucun JavaScript et conditionne sa CSS. Cependant, multiplier les plugins mal conçus ou les traitements inutiles peut toujours dégrader les performances.

Peut-on placer ce code dans functions.php ?

Vous pourriez y intégrer certaines fonctions, mais le comportement dépendrait alors du thème actif. Notre encadré et ses réglages doivent survivre à une refonte. Une extension autonome constitue donc ici le choix le plus cohérent.

Le message accepte-t-il du HTML ?

Non. Cette version conserve du texte simple et ses retours à la ligne. Pour accepter des liens ou d’autres balises, définissez une liste explicite avec les outils WordPress adaptés. Il faudra également modifier le nettoyage, le rendu et les tests.

Les styles fonctionnent-ils partout où le shortcode apparaît ?

La détection automatique couvre les articles et pages individuels dont le contenu principal contient la balise. Pour un widget, un modèle ou une composition synchronisée, utilisez le filtre prévu afin de charger la CSS sur les requêtes concernées.

Peut-on publier cette extension sur WordPress.org ?

Cette base peut évoluer vers un projet distribué publiquement. Toutefois, la publication demande une revue supplémentaire : nom disponible, documentation, licence, traductions, tests et conformité aux règles du répertoire. Le tutoriel ne constitue pas une validation de publication.

Faire évoluer votre extension sans perdre sa simplicité

Vous disposez désormais d’une extension qui couvre un cycle complet : configuration, contrôle des entrées, affichage, styles, traductions et suppression volontaire des données. Chaque étape répond à un besoin concret, avec un périmètre que vous pouvez expliquer et tester.

Pour la suite, choisissez une évolution mesurable. Vous pourriez ajouter plusieurs encadrés, un bloc dynamique ou une condition d’affichage. Cependant, chacune de ces fonctions modifierait le stockage, l’interface ou les règles de chargement. Écrivez d’abord le comportement attendu, puis faites évoluer votre base progressivement.

Sources et documentation

Laisser un commentaire