Si vous avez déjà collé un “petit snippet” dans functions.php et que tout le site est parti en écran blanc, créer un mini-plugin propre est souvent la solution la plus simple (et la plus safe) sur WordPress 6.9.4.

Ce qu’on va construire

Vous allez créer un plugin WordPress complet (pas juste un “Hello World” minimal), compatible WordPress 6.9.4+ et PHP 8.1+, avec :

  • un affichage “Hello World” sur le site (frontend) via un hook (action) adapté,
  • une page d’administration pour activer/désactiver le message,
  • un shortcode pour l’insérer où vous voulez (pratique avec Divi 5, Elementor, Avada),
  • un chargement propre de CSS/JS (enqueue),
  • un formulaire sécurisé (nonce, capacités) et des données nettoyées (sanitization).

À la fin, vous saurez :

  • où mettre le code (et où ne jamais le mettre),
  • ce qu’est un hook (action/filtre) et comment l’utiliser sans casser le site,
  • comment structurer un plugin “propre” même si vous débutez.

Résumé rapide

  • Vous créez un dossier dans wp-content/plugins/ et un fichier principal avec l’en-tête du plugin.
  • Vous utilisez une action (hook) pour afficher un message sur le frontend sans toucher au thème.
  • Vous stockez un réglage avec l’API Options (une option WordPress), et vous ajoutez une page dans l’admin.
  • Vous sécurisez le formulaire avec un nonce et une vérification de capacité (manage_options).
  • Vous ajoutez un shortcode pour l’utiliser dans Divi/Elementor/Avada.
  • Vous chargez CSS/JS via wp_enqueue_scripts (et pas en “echo <style>”).

Quand utiliser cette solution

  • Vous voulez ajouter une fonctionnalité simple et réutilisable, indépendante du thème (ex : message, bannière, widget, intégration).
  • Vous utilisez un page builder (Divi 5 / Elementor / Avada) et vous voulez un shortcode stable.
  • Vous voulez éviter de modifier le thème (ou vous changez de thème régulièrement).
  • Vous voulez apprendre les bases “saines” : hooks, options, sécurité, enqueue.

Dans mon expérience, c’est aussi le bon choix quand vous avez déjà 10 snippets dispersés dans un thème enfant, un plugin de snippets et un “Code Snippets” : centraliser dans un plugin réduit beaucoup les bugs.

Quand ne PAS utiliser cette solution

  • Vous voulez juste coller un texte dans une page : utilisez l’éditeur de blocs ou votre builder.
  • Vous avez besoin d’une fonctionnalité existante : installez un plugin maintenu plutôt que réinventer (SEO, cache, formulaires, etc.).
  • Vous n’avez pas d’environnement de test et vous comptez expérimenter directement en production : risque élevé d’écran blanc si une erreur PHP se glisse.
  • Votre hébergement est encore en PHP 7.x : ce tutoriel cible PHP 8.1+ (recommandé en 2026).

Avant de commencer (prérequis)

Prérequis techniques

  • WordPress : 6.9.4 ou plus récent.
  • PHP : 8.1 minimum (8.2/8.3 souvent disponible, mais 8.1 est la base ici).
  • Accès fichiers : FTP/SFTP, cPanel, ou gestionnaire de fichiers de votre hébergeur.
  • Thème enfant : activé (même si on ne va pas y mettre le code, c’est une bonne base de travail).

Avant toute modification : sauvegarde + environnement

Faites une sauvegarde (fichiers + base de données) et, si possible, testez sur un site de staging. Le risque n’est pas “WordPress qui casse tout”, c’est une simple erreur de syntaxe PHP (point-virgule oublié) qui déclenche une erreur fatale.

Outils utiles

  • Un éditeur de code qui colore la syntaxe (VS Code, PhpStorm).
  • Le mode debug WordPress (facultatif mais très utile).

Mini-glossaire (pour ne pas se perdre)

  • Plugin : extension qui ajoute du code à WordPress sans modifier le cœur (core) ni le thème.
  • Hook : “point d’accroche” dans WordPress. Il y a deux types :
    • Action : vous exécutez du code à un moment donné (ex : afficher quelque chose).
    • Filtre : vous modifiez une valeur (ex : changer le contenu d’un texte) et vous la retournez.
  • Option : valeur stockée en base via l’API Options (ex : un réglage on/off).
  • Nonce : jeton anti-CSRF pour sécuriser un formulaire WordPress.
  • Enqueue : méthode officielle pour charger CSS/JS (évite les conflits et les doublons).

Résultat attendu à la fin de cette section

Vous devez avoir : un site sauvegardé, un accès aux fichiers, et la certitude que votre site tourne bien sur WordPress 6.9.4 et PHP 8.1+.


Étape 1 : Créer la structure du plugin (dossier + fichier principal)

Un plugin WordPress “existe” dès qu’il y a un dossier dans wp-content/plugins et un fichier PHP avec un en-tête (header) reconnu par WordPress.

Où cliquer / où créer les fichiers

  1. Ouvrez les fichiers de votre site (FTP/SFTP ou gestionnaire de fichiers).
  2. Allez dans wp-content/plugins/.
  3. Créez un dossier : hello-world-complet.
  4. Dans ce dossier, créez un fichier : hello-world-complet.php.

Code complet de l’étape 1 (fichier principal)

Collez ceci dans wp-content/plugins/hello-world-complet/hello-world-complet.php :

<?php
/**
 * Plugin Name: Hello World Complet (Tutoriel)
 * Description: Un premier plugin WordPress complet : message frontend, page admin, shortcode, assets, sécurité.
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 8.1
 * Author: Votre Nom
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: hello-world-complet
 *
 * Ce fichier est le point d'entrée du plugin.
 */

if ( ! defined( 'ABSPATH' ) ) {
	// Sécurité : empêche l'accès direct au fichier PHP.
	exit;
}

define( 'HWC_VERSION', '1.0.0' );
define( 'HWC_PLUGIN_FILE', __FILE__ );
define( 'HWC_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'HWC_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

/**
 * Valeur par défaut de notre option.
 */
function hwc_default_options(): array {
	return array(
		'enabled' => true,
		'message' => 'Hello World ! (depuis mon premier plugin)',
	);
}

Activer le plugin

  1. Dans l’admin WordPress, allez dans Extensions > Extensions installées.
  2. Repérez Hello World Complet (Tutoriel).
  3. Cliquez Activer.

Résultat attendu

Vous voyez le plugin activé, sans erreur. Rien ne s’affiche encore sur le site : c’est normal, on n’a branché aucun hook.


Étape 2 : Afficher “Hello World” sur le site (frontend) proprement

On va utiliser une action (hook d’action) pour injecter un petit bandeau sur le site. J’évite volontairement de modifier the_content au début : c’est un filtre utile, mais ça crée vite des effets de bord (builders, extraits, boucles personnalisées).

Principe

  • On accroche une fonction à wp_footer (action exécutée juste avant </body>).
  • On affiche un bloc HTML simple.
  • On conditionne l’affichage à un réglage (option) qu’on ajoutera ensuite.

Code à ajouter (dans le même fichier)

Ajoutez ceci à la fin de hello-world-complet.php :

/**
 * Récupère les options du plugin (avec valeurs par défaut).
 */
function hwc_get_options(): array {
	$defaults = hwc_default_options();

	// On récupère l'option stockée en base (table wp_options).
	$saved = get_option( 'hwc_options', array() );

	if ( ! is_array( $saved ) ) {
		$saved = array();
	}

	// On fusionne : les valeurs sauvegardées écrasent les défauts.
	return array_merge( $defaults, $saved );
}

/**
 * Affiche le message en bas de page (frontend).
 * Hook (action) : wp_footer.
 */
function hwc_render_frontend_message(): void {
	if ( is_admin() ) {
		return;
	}

	$options = hwc_get_options();

	if ( empty( $options['enabled'] ) ) {
		return;
	}

	$message = (string) $options['message'];

	// Sécurité XSS : on échappe le texte affiché.
	$message_escaped = esc_html( $message );

	echo '<div class="hwc-hello" role="note">' . $message_escaped . '</div>';
}
add_action( 'wp_footer', 'hwc_render_frontend_message', 20 );

Résultat attendu

En rechargeant une page du site (côté visiteur), vous devez voir, tout en bas, un texte “Hello World ! (depuis mon premier plugin)”.

Capture textuelle attendue : un petit bloc de texte en bas de page, après le contenu, sans mise en forme particulière.


Étape 3 : Ajouter une page d’admin pour activer/désactiver le message

On va créer une page dans l’admin, menu “Réglages”, qui permet :

  • d’activer/désactiver le bandeau,
  • de changer le texte.

Ce qui se passe en coulisses

  • add_options_page() ajoute une entrée sous “Réglages”.
  • Un formulaire POST enregistre une option via update_option().
  • On vérifiera la sécurité à l’étape 6 (nonce + capacité). Ici, on prépare la structure.

Code à ajouter

Ajoutez ceci dans hello-world-complet.php (après vos fonctions existantes) :

/**
 * Ajoute une page de réglages dans l'admin.
 */
function hwc_register_settings_page(): void {
	add_options_page(
		'Hello World Complet',
		'Hello World Complet',
		'manage_options',
		'hwc-settings',
		'hwc_render_settings_page'
	);
}
add_action( 'admin_menu', 'hwc_register_settings_page' );

/**
 * Affiche la page de réglages (HTML).
 * Note : on ajoute la sécurité (nonce + vérifs) à l'étape 6.
 */
function hwc_render_settings_page(): void {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'Vous n’avez pas les droits suffisants pour accéder à cette page.', 'hello-world-complet' ) );
	}

	$options = hwc_get_options();
	$enabled = ! empty( $options['enabled'] );
	$message = (string) $options['message'];

	?>
	<div class="wrap">
		<h1>Hello World Complet</h1>

		<form method="post" action="">
			<table class="form-table" role="presentation">
				<tbody>
					<tr>
						<th scope="row">Activer le message</th>
						<td>
							<label>
								<input type="checkbox" name="hwc_enabled" value="1" <?php checked( $enabled ); ?> />
								Afficher le bandeau “Hello World”
							</label>
						</td>
					</tr>

					<tr>
						<th scope="row">Texte</th>
						<td>
							<input type="text" class="regular-text" name="hwc_message" value="<?php echo esc_attr( $message ); ?>" />
							<p class="description">Exemple : “Bienvenue sur mon site”.</p>
						</td>
					</tr>
				</tbody>
			</table>

			<p>
				<input type="submit" class="button button-primary" name="hwc_save" value="Enregistrer" />
			</p>
		</form>
	</div>
	<?php
}

Résultat attendu

  1. Allez dans Réglages > Hello World Complet.
  2. Vous voyez un formulaire avec une case à cocher et un champ texte.

Capture textuelle attendue : une page “Hello World Complet” dans l’admin, avec un tableau de réglages (style WordPress).

À ce stade, cliquer “Enregistrer” ne fait rien (on n’a pas codé la sauvegarde). C’est volontaire.


Étape 4 : Ajouter un shortcode (pour Divi/Elementor/Avada)

Un shortcode est un petit code entre crochets, par exemple [hello_world], que WordPress remplace par du contenu dynamique. Les builders savent presque tous insérer des shortcodes facilement.

Code à ajouter

/**
 * Shortcode : [hello_world]
 * Retourne le message sous forme de HTML.
 */
function hwc_shortcode_hello_world( $atts = array() ): string {
	$options = hwc_get_options();

	if ( empty( $options['enabled'] ) ) {
		return '';
	}

	$atts = shortcode_atts(
		array(
			'tag' => 'div',
			'class' => 'hwc-hello-inline',
		),
		(array) $atts,
		'hello_world'
	);

	$tag = strtolower( (string) $atts['tag'] );

	// On limite les tags autorisés pour éviter les surprises.
	$allowed_tags = array( 'div', 'p', 'span' );
	if ( ! in_array( $tag, $allowed_tags, true ) ) {
		$tag = 'div';
	}

	$class = sanitize_html_class( (string) $atts['class'] );
	$message = esc_html( (string) $options['message'] );

	return '<' . $tag . ' class="' . esc_attr( $class ) . '">' . $message . '</' . $tag . '>';
}
add_shortcode( 'hello_world', 'hwc_shortcode_hello_world' );

Résultat attendu

  1. Créez une page de test.
  2. Ajoutez un bloc “Code court / Shortcode” (ou l’équivalent dans votre builder).
  3. Insérez : [hello_world].

Capture textuelle attendue : le texte “Hello World …” s’affiche à l’endroit exact où vous avez mis le shortcode.


Étape 5 : Charger du CSS/JS correctement (enqueue) + exemple concret

Le chargement “propre” des assets évite deux problèmes que je vois tout le temps : CSS injecté 10 fois, et JS qui se charge sur l’admin ou sur des pages inutiles.

Créer les fichiers CSS/JS

  1. Dans hello-world-complet, créez un dossier assets.
  2. Dans assets, créez :
    • hello.css
    • hello.js

Contenu de assets/hello.css

.hwc-hello {
	position: fixed;
	left: 16px;
	right: 16px;
	bottom: 16px;
	padding: 12px 14px;
	background: #111;
	color: #fff;
	border-radius: 10px;
	font-size: 14px;
	line-height: 1.4;
	z-index: 9999;
	box-shadow: 0 10px 30px rgba(0,0,0,.25);
}

.hwc-hello-inline {
	padding: 10px 12px;
	border-left: 4px solid #111;
	background: #f6f7f7;
}

Contenu de assets/hello.js

(() => {
  // Petit exemple : au clic sur le bandeau, on le masque.
  document.addEventListener('click', (e) => {
    const banner = e.target.closest('.hwc-hello');
    if (!banner) return;
    banner.style.display = 'none';
  });
})();

Enqueue côté frontend

Ajoutez ceci dans hello-world-complet.php :

/**
 * Charge le CSS/JS sur le frontend.
 */
function hwc_enqueue_frontend_assets(): void {
	if ( is_admin() ) {
		return;
	}

	$options = hwc_get_options();
	if ( empty( $options['enabled'] ) ) {
		// Si le plugin est désactivé, inutile de charger les assets.
		return;
	}

	wp_enqueue_style(
		'hwc-hello',
		HWC_PLUGIN_URL . 'assets/hello.css',
		array(),
		HWC_VERSION
	);

	wp_enqueue_script(
		'hwc-hello',
		HWC_PLUGIN_URL . 'assets/hello.js',
		array(),
		HWC_VERSION,
		true
	);
}
add_action( 'wp_enqueue_scripts', 'hwc_enqueue_frontend_assets' );

Résultat attendu

Rechargez le site : le bandeau en bas est maintenant stylé (fond sombre, arrondi). Si vous cliquez dessus, il disparaît.

Capture textuelle attendue : un bandeau “toast” sombre en bas de page.


Étape 6 : Sécuriser le formulaire (nonce + capacités) et nettoyer les données

Sans nonce, n’importe quel site externe peut tenter de vous faire soumettre le formulaire à votre insu (attaque CSRF). Sans nettoyage, vous risquez d’enregistrer des données inattendues (et parfois d’ouvrir une porte à du XSS si vous affichez ensuite ces valeurs).

Ajouter un nonce dans le formulaire

Dans la fonction hwc_render_settings_page(), juste après <form ...>, ajoutez :

<?php wp_nonce_field( 'hwc_save_settings', 'hwc_nonce' ); ?>

Gérer la sauvegarde (POST) de manière sûre

Ajoutez cette fonction dans hello-world-complet.php :

/**
 * Traite la sauvegarde des réglages.
 * Hook (action) : admin_init (exécuté sur l'admin).
 */
function hwc_handle_settings_save(): void {
	if ( ! is_admin() ) {
		return;
	}

	// On ne traite que notre formulaire.
	if ( empty( $_POST['hwc_save'] ) ) {
		return;
	}

	// Vérification de capacité : seuls les admins (ou rôles équivalents) peuvent enregistrer.
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	// Vérification nonce (anti-CSRF).
	$nonce = isset( $_POST['hwc_nonce'] ) ? (string) $_POST['hwc_nonce'] : '';
	if ( ! wp_verify_nonce( $nonce, 'hwc_save_settings' ) ) {
		return;
	}

	// Nettoyage des données (sanitization).
	$enabled = ! empty( $_POST['hwc_enabled'] );

	$message_raw = isset( $_POST['hwc_message'] ) ? (string) wp_unslash( $_POST['hwc_message'] ) : '';
	$message     = sanitize_text_field( $message_raw );

	$options = array(
		'enabled' => $enabled,
		'message' => $message,
	);

	update_option( 'hwc_options', $options );

	// Redirection pour éviter la resoumission du formulaire au refresh.
	$redirect_url = add_query_arg(
		array(
			'page' => 'hwc-settings',
			'hwc_updated' => '1',
		),
		admin_url( 'options-general.php' )
	);

	wp_safe_redirect( $redirect_url );
	exit;
}
add_action( 'admin_init', 'hwc_handle_settings_save' );

Afficher un message “Réglages enregistrés”

Dans hwc_render_settings_page(), juste après le <h1>, ajoutez :

<?php if ( isset( $_GET['hwc_updated'] ) && '1' === (string) $_GET['hwc_updated'] ) : ?>
	<div class="notice notice-success is-dismissible">
		<p><?php echo esc_html__( 'Réglages enregistrés.', 'hello-world-complet' ); ?></p>
	</div>
<?php endif; ?>

Résultat attendu

  1. Allez dans Réglages > Hello World Complet.
  2. Décochez “Activer le message”, enregistrez.
  3. Rechargez le frontend : le bandeau a disparu (et les assets ne se chargent plus).
  4. Recochez, changez le texte, enregistrez : le nouveau texte s’affiche.

Capture textuelle attendue : une notice WordPress “Réglages enregistrés.” et un changement immédiat sur le site.


Le résultat complet

Si vous préférez tout copier d’un coup, voici le fichier complet hello-world-complet.php. Vérifiez bien que vos fichiers assets/hello.css et assets/hello.js existent aussi (sinon le CSS/JS ne se chargera pas).

<?php
/**
 * Plugin Name: Hello World Complet (Tutoriel)
 * Description: Un premier plugin WordPress complet : message frontend, page admin, shortcode, assets, sécurité.
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 8.1
 * Author: Votre Nom
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: hello-world-complet
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

define( 'HWC_VERSION', '1.0.0' );
define( 'HWC_PLUGIN_FILE', __FILE__ );
define( 'HWC_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'HWC_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

function hwc_default_options(): array {
	return array(
		'enabled' => true,
		'message' => 'Hello World ! (depuis mon premier plugin)',
	);
}

function hwc_get_options(): array {
	$defaults = hwc_default_options();
	$saved    = get_option( 'hwc_options', array() );

	if ( ! is_array( $saved ) ) {
		$saved = array();
	}

	return array_merge( $defaults, $saved );
}

function hwc_render_frontend_message(): void {
	if ( is_admin() ) {
		return;
	}

	$options = hwc_get_options();

	if ( empty( $options['enabled'] ) ) {
		return;
	}

	$message = esc_html( (string) $options['message'] );

	echo '<div class="hwc-hello" role="note">' . $message . '</div>';
}
add_action( 'wp_footer', 'hwc_render_frontend_message', 20 );

function hwc_enqueue_frontend_assets(): void {
	if ( is_admin() ) {
		return;
	}

	$options = hwc_get_options();
	if ( empty( $options['enabled'] ) ) {
		return;
	}

	wp_enqueue_style(
		'hwc-hello',
		HWC_PLUGIN_URL . 'assets/hello.css',
		array(),
		HWC_VERSION
	);

	wp_enqueue_script(
		'hwc-hello',
		HWC_PLUGIN_URL . 'assets/hello.js',
		array(),
		HWC_VERSION,
		true
	);
}
add_action( 'wp_enqueue_scripts', 'hwc_enqueue_frontend_assets' );

function hwc_shortcode_hello_world( $atts = array() ): string {
	$options = hwc_get_options();

	if ( empty( $options['enabled'] ) ) {
		return '';
	}

	$atts = shortcode_atts(
		array(
			'tag'   => 'div',
			'class' => 'hwc-hello-inline',
		),
		(array) $atts,
		'hello_world'
	);

	$tag = strtolower( (string) $atts['tag'] );
	$allowed_tags = array( 'div', 'p', 'span' );
	if ( ! in_array( $tag, $allowed_tags, true ) ) {
		$tag = 'div';
	}

	$class   = sanitize_html_class( (string) $atts['class'] );
	$message = esc_html( (string) $options['message'] );

	return '<' . $tag . ' class="' . esc_attr( $class ) . '">' . $message . '</' . $tag . '>';
}
add_shortcode( 'hello_world', 'hwc_shortcode_hello_world' );

function hwc_register_settings_page(): void {
	add_options_page(
		'Hello World Complet',
		'Hello World Complet',
		'manage_options',
		'hwc-settings',
		'hwc_render_settings_page'
	);
}
add_action( 'admin_menu', 'hwc_register_settings_page' );

function hwc_handle_settings_save(): void {
	if ( ! is_admin() ) {
		return;
	}

	if ( empty( $_POST['hwc_save'] ) ) {
		return;
	}

	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	$nonce = isset( $_POST['hwc_nonce'] ) ? (string) $_POST['hwc_nonce'] : '';
	if ( ! wp_verify_nonce( $nonce, 'hwc_save_settings' ) ) {
		return;
	}

	$enabled = ! empty( $_POST['hwc_enabled'] );

	$message_raw = isset( $_POST['hwc_message'] ) ? (string) wp_unslash( $_POST['hwc_message'] ) : '';
	$message     = sanitize_text_field( $message_raw );

	$options = array(
		'enabled' => $enabled,
		'message' => $message,
	);

	update_option( 'hwc_options', $options );

	$redirect_url = add_query_arg(
		array(
			'page'        => 'hwc-settings',
			'hwc_updated' => '1',
		),
		admin_url( 'options-general.php' )
	);

	wp_safe_redirect( $redirect_url );
	exit;
}
add_action( 'admin_init', 'hwc_handle_settings_save' );

function hwc_render_settings_page(): void {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'Vous n’avez pas les droits suffisants pour accéder à cette page.', 'hello-world-complet' ) );
	}

	$options = hwc_get_options();
	$enabled = ! empty( $options['enabled'] );
	$message = (string) $options['message'];
	?>
	<div class="wrap">
		<h1>Hello World Complet</h1>

		<?php if ( isset( $_GET['hwc_updated'] ) && '1' === (string) $_GET['hwc_updated'] ) : ?>
			<div class="notice notice-success is-dismissible">
				<p><?php echo esc_html__( 'Réglages enregistrés.', 'hello-world-complet' ); ?></p>
			</div>
		<?php endif; ?>

		<form method="post" action="">
			<?php wp_nonce_field( 'hwc_save_settings', 'hwc_nonce' ); ?>

			<table class="form-table" role="presentation">
				<tbody>
					<tr>
						<th scope="row">Activer le message</th>
						<td>
							<label>
								<input type="checkbox" name="hwc_enabled" value="1" <?php checked( $enabled ); ?> />
								Afficher le bandeau “Hello World”
							</label>
						</td>
					</tr>

					<tr>
						<th scope="row">Texte</th>
						<td>
							<input type="text" class="regular-text" name="hwc_message" value="<?php echo esc_attr( $message ); ?>" />
							<p class="description">Exemple : “Bienvenue sur mon site”.</p>
						</td>
					</tr>
				</tbody>
			</table>

			<p>
				<input type="submit" class="button button-primary" name="hwc_save" value="Enregistrer" />
			</p>
		</form>
	</div>
	<?php
}

Personnalisation rapide

  • Changez le texte par défaut dans hwc_default_options().
  • Changez l’emplacement du bandeau en remplaçant wp_footer par wp_body_open si votre thème le supporte (souvent le cas sur les thèmes récents). Gardez wp_footer si vous voulez un comportement stable.
  • Ajoutez des attributs au shortcode : [hello_world tag="p" class="ma-classe"].

Adapter pour Divi 5 / Elementor / Avada

Divi 5

  • Ajoutez un module Code ou Texte (selon votre configuration).
  • Collez [hello_world].
  • Si Divi n’interprète pas le shortcode dans un module Texte (ça arrive selon les réglages), utilisez le module “Code” ou un module dédié “Shortcode” si disponible.

Astuce que j’utilise souvent : créez une section “bannière” dans Divi et mettez le shortcode dedans, puis gérez l’affichage global via l’option “enabled” du plugin.

Elementor

  • Utilisez le widget Shortcode.
  • Collez [hello_world].
  • Si vous utilisez la version Pro, vous pouvez aussi l’injecter via un template (Header/Footer) et le contrôler côté plugin.

Avada (Fusion Builder)

  • Ajoutez l’élément Shortcode (ou un bloc texte qui interprète les shortcodes).
  • Collez [hello_world].

Compatibilité réelle (ce que j’ai vu sur le terrain)

Les builders aiment bien “réécrire” le contenu. C’est pour ça que le bandeau via wp_footer est souvent plus stable qu’un filtre the_content. Le shortcode, lui, reste le meilleur point d’intégration côté builder.


Vérification finale

  1. Admin : Réglages > Hello World Complet existe et le formulaire s’enregistre.
  2. Frontend : si activé, le bandeau s’affiche et est stylé.
  3. Shortcode : [hello_world] affiche le message au bon endroit.
  4. Sécurité :
    • si vous rechargez la page après sauvegarde, pas de popup “renvoyer le formulaire” (redirection OK),
    • si vous êtes connecté avec un rôle non-admin, vous ne pouvez pas accéder à la page de réglages.
  5. Performance : désactivez le message, puis vérifiez que CSS/JS ne se chargent plus (via l’inspecteur réseau du navigateur si vous savez le faire).

Si le résultat n’est pas celui attendu

Symptôme Cause probable Vérification Solution
Le plugin n’apparaît pas dans “Extensions” Fichier au mauvais endroit ou en-tête absent Vérifiez le chemin exact : wp-content/plugins/hello-world-complet/hello-world-complet.php Corrigez le dossier/fichier et assurez-vous que l’en-tête “Plugin Name” est présent
Écran blanc / erreur critique à l’activation Erreur de syntaxe (point-virgule, parenthèse) ou PHP trop ancien Regardez wp-content/debug.log si WP_DEBUG est activé, ou les logs serveur Corrigez la ligne indiquée, vérifiez PHP 8.1+, désactivez le plugin via FTP si nécessaire
Le bandeau ne s’affiche pas Option désactivée, cache, ou thème qui ne déclenche pas wp_footer (rare mais vu sur des thèmes mal codés) Désactivez le cache, passez sur un thème par défaut pour tester Videz les caches, testez wp_body_open ou corrigez le thème (idéalement)
Le CSS/JS ne se charge pas Fichiers assets manquants, mauvais nom, cache, minification agressive Vérifiez l’existence de assets/hello.css et assets/hello.js Créez les fichiers, videz cache, désactivez temporairement l’optimisation
Le shortcode s’affiche en texte (ex : “[hello_world]”) Shortcodes désactivés dans ce contexte (ou widget/module qui ne les interprète pas) Testez dans une page classique avec bloc “Code court” Utilisez le widget/module “Shortcode” du builder ou changez de bloc

3 vérifications rapides qui résolvent souvent tout

  • Cache : videz le cache de votre plugin de cache + le cache navigateur (Ctrl/Cmd+Shift+R).
  • Emplacement du code : assurez-vous de ne pas avoir collé du code PHP dans un champ “CSS personnalisé” ou dans un constructeur.
  • Conflits : désactivez temporairement les plugins d’optimisation (minify) si les assets ne chargent pas.

Pièges et erreurs courantes

Erreur Cause Solution
Copier le code dans functions.php au lieu du plugin Habitude “snippet rapide” Gardez le code dans le plugin pour qu’il survive aux changements de thème
Oublier un ; ou une accolade } Éditeur sans coloration / copier-coller partiel Utilisez un éditeur de code, comparez avec le “résultat complet”
Utiliser un hook inadapté (ex : init pour afficher du HTML) Confusion action/filtre, ou tuto ancien Affichage frontend : wp_footer, wp_body_open, ou un shortcode
Le formulaire enregistre n’importe quoi Pas de sanitization / pas de wp_unslash() Nettoyez avec sanitize_text_field() et utilisez wp_unslash() sur $_POST
Le CSS/JS se charge partout (y compris admin) Hook admin_enqueue_scripts confondu avec wp_enqueue_scripts, ou condition manquante Chargez côté frontend via wp_enqueue_scripts + condition “enabled”
Snippet cassé par un plugin de snippets Deux versions du même code actives Désactivez l’ancien snippet, gardez une seule source de vérité

Variante / alternative

Méthode sans code : plugin “Code Snippets” (ou équivalent)

Si votre objectif est juste d’ajouter une fonction simple, un plugin de gestion de snippets peut suffire. Avantage : interface, activation/désactivation rapide. Inconvénient : vous empilez des snippets, et le jour où vous migrez, vous oubliez souvent d’exporter.

  • Alternative pratique pour débuter, mais je recommande de passer au plugin custom dès que vous avez 2–3 fonctionnalités.

Méthode plus “pro” : plugin orienté classes + autoload

Quand le plugin grossit, vous séparerez en fichiers (includes/), vous utiliserez des classes, et potentiellement un autoload Composer. Pour un premier plugin, je reste volontairement en fonctions simples : moins de magie, plus facile à déboguer.


Conseils sécurité, performance et maintenance

  • Ne modifiez jamais le core : tout doit vivre dans votre plugin ou votre thème enfant.
  • Échappement systématique : tout ce qui est affiché doit être échappé (esc_html, esc_attr, etc.). C’est la base contre le XSS.
  • Nettoyage des entrées : tout ce qui vient de $_POST doit être nettoyé (ici sanitize_text_field).
  • Capacités : vérifiez toujours current_user_can() pour les pages/actions admin.
  • Nonces : un formulaire admin sans nonce finit tôt ou tard par poser problème.
  • Performance : ne chargez pas CSS/JS si la fonctionnalité est désactivée. Sur des sites avec cache + minification, ça évite des fichiers inutiles.
  • Maintenance : versionnez votre plugin (même juste un numéro) et gardez un changelog si vous le déployez sur plusieurs sites.

Pour aller plus loin

  • Ajouter une option “position” (bas gauche, bas centre, haut) et adapter le CSS.
  • Remplacer le simple champ texte par un champ textarea, avec une liste limitée de balises autorisées via wp_kses().
  • Ajouter un affichage conditionnel : seulement sur la page d’accueil, seulement pour les visiteurs non connectés, etc.
  • Créer un bloc Gutenberg (plus avancé), en gardant le shortcode pour compatibilité builders.
  • Ajouter une désinstallation propre : supprimer l’option à la désinstallation (fichier uninstall.php).

Ressources


FAQ

Est-ce que ce plugin est compatible WordPress 6.9.4 ?

Oui. Le code utilise des APIs stables (hooks, options, nonces, enqueue) et cible PHP 8.1+. Rien ici ne dépend d’une nouveauté fragile.

Où est-ce que je dois coller le code exactement ?

Dans wp-content/plugins/hello-world-complet/hello-world-complet.php. Pas dans wp-includes, pas dans un fichier du core, et idéalement pas dans functions.php pour ce tutoriel.

Je n’ai pas accès à FTP/SFTP, je fais comment ?

Sans accès fichiers, c’est compliqué de créer un plugin. Certains hébergeurs proposent un gestionnaire de fichiers dans cPanel. Sinon, demandez l’accès à votre prestataire/hébergeur.

Pourquoi utiliser wp_footer au lieu de modifier le contenu des articles ?

wp_footer est un point d’accroche stable, indépendant des builders et des templates. Modifier the_content (filtre) marche, mais j’ai souvent vu des doubles affichages ou des comportements bizarres avec des pages construites.

Est-ce que je peux afficher le message uniquement sur certaines pages ?

Oui. Dans hwc_render_frontend_message(), ajoutez des conditions WordPress comme is_front_page(), is_page(123), is_singular('post'), etc.

Pourquoi wp_unslash() sur $_POST ?

WordPress ajoute des slashes sur certaines entrées (héritage historique). wp_unslash() remet la chaîne “normale” avant nettoyage. C’est un détail, mais c’est exactement le genre de détail qui évite des backslashes bizarres dans vos options.

Je peux autoriser du HTML dans le message ?

Oui, mais faites-le proprement avec wp_kses() (liste blanche de balises). Ne stockez pas du HTML brut sans filtrage : vous augmentez le risque XSS, surtout si d’autres rôles peuvent modifier le réglage.

Comment désinstaller proprement (supprimer l’option) ?

Ajoutez un fichier uninstall.php dans le dossier du plugin, et supprimez l’option via delete_option('hwc_options') après avoir vérifié defined('WP_UNINSTALL_PLUGIN'). Faites-le seulement si vous êtes sûr de ne pas vouloir conserver les réglages.

Pourquoi ne pas utiliser l’API Settings (register_setting) dès le début ?

L’API Settings est très bien, mais elle ajoute une couche de concepts (sections, champs, callbacks). Pour un premier plugin, ce formulaire “manuel” avec nonce + sanitization est plus simple à suivre. Une fois à l’aise, vous pourrez migrer vers register_setting().

Mon site passe en “Erreur critique” quand j’active le plugin, que faire vite ?

Désactivez le plugin en renommant son dossier via FTP (ex : hello-world-complet_OFF). Ensuite, regardez les logs (ou wp-content/debug.log) pour trouver la ligne fautive. Dans 80% des cas : une accolade manquante ou un copier-coller incomplet.