Nicolas Juen

Menu

Créer une extension WordPress : Les premières étapes

Plus de 8 minutes 🙂

Comment commencer son extension

Créer une extension WordPress demande toujours un petit temps de réflexion, les questions que j’ai l’habitude de me poser sont les suivantes :

  • Dans quels contextes fonctionne-t-il ? Admin ? Front ?
  • Y-a-t’il une page d’option ? intégrée aux réglages WordPress ? un bloc complet ?
  • Des javascripts ? des css ? en front, en backoffice ou les deux ?
  • Est-il compliqué ?
  • Dans quelle mesure l’utilisateur peut modifier le comportement de mon plugin ?

En répondant à ces petites questions, on peut vite se rendre compte de l’ampleur de la tâche. Plus une extension sera compliquée, plus l’utilisation de classes est préconisé.
Effectivement la structure des classes nous permet de se dédouaner de noms de fonctions avec des préfixes pour ne pas entrer en conflit avec d’autres fonctions.

Une extension simple

Si vous créez une extension simple, qui va faire des actions basiques en admin ou en front, pas besoin de créer un dossier pour y mettre un seul fichier !

Bien sûr si c’est pour le mettre sur le dépôt officiel, la création d’un dossier est indispensable, rien que pour embarquer le fichier readme.txt ou les fichiers de traduction.

Je ne vais pas vous détailler la création d’une extension simple, vous pouvez vous inspirer de la suite avec l’extension un peu plus compliquée et structurée. Il suffira de retirer les fichiers inutiles.

Une extension élaborée

Prenons le cas d’un plugin qui a une partie en admin, une partie en front, des javascript en admin et en front, de même pour les CSS. Forcément avec ces javascript on va travailler avec une libraire comme jquery-ui ou tout autre librairie, donc on va vite pouvoir s’emmêler les pinceaux…

La méthode que je propose n’est pas parfaite, mais elle peut être une solution de développement.

L’arborescence

Voici ce à quoi pourrait ressembler une arborescence d’extension que nous allons intituler « mon-extension »

  • my-extension – le nom du dossier racine, qui porte la plupart du temps le slug de l’extension
    • my-extension.php – le nom du fichier qui sera lu par WordPress, d’habitude c’est le même nom que le slug du dossier parent, toutes les informations de base du plugin s’y retrouvent
    • classes – le dossier d’inclusion des fichiers php nécessaires au plugin, ce dossier contient les fichiers dont nous auront besoin. Il peut contenir vos librairies externes en php et bien sûr toutes vos classes
      • main.php  – c’est là où vous pourrez stocker toutes vos fonctionnalités qui font effet en front, les filtres, les actions et les inclusion de javascript/css.
      • admin – le dossier où ranger vos classes pour l’admin
        • main.php – c’est là que les fonctionnalités de l’admin seront crées, les actions, les filtres, les inclusions de script et de css aussi.
        • page.php – c’est dans ce fichier que l’ont peut implémenter les fonctionnalités telles que la page d’option.
    • functions
      • plugin.php – dans ce fichier on est susceptible de mettre toutes nos fonctions publiques, mais aussi celles d’activation et de désactivation de plugin.
      • tpl.php – dans ce fichier vous pourrez mettre les fonctions que l’on appelle depuis de thème.
    • assets- c’est là que vous allez stocker toutes les ressources de vos extensions, comme les librairies, les styles et les images.
      • css – vos fichiers css, je vous recommande de les préfixer avec des « admin- » ou des « front- » pour que vous les reconnaissiez très facilement, de même créer des fichier minifiés en gardant une version non minifiée.
      • js – pareil que pour le css
      • images – stocker ici toutes les icônes et les images intégrées à votre extension.
    • languages – Ici mettez tous les fichiers de traduction que vous avez créé ( si vous parlez plusieurs langues ça peut vous aider 😉 ).

Le fichier mon-extension.php

La base

C’est là où se retrouvent toutes les informations et l’initialisation de notre extension. Le fichier readme.txt n’est nécessaire que pour une extension du dépôt officiel, néanmoins il faut certains informations au minimum.

Voici ce à quoi pourrait ressembler l’entête de notre fichier :

[pastacode provider= »manual » lang= »php »]


/*
Plugin Name: My Extension
Plugin URI: http://nicolas-juen.fr
Description: Do soooooo much thing i can't tell you here..
Version: 1.0
Author: Rahe
Author URI: https://blog.nicolas-juen.fr
Text Domain: my-extension
Domain Path: languages
*/

[/pastacode]

Avec ce petit bout de code, notre extension est reconnue par WoordPress et nous pouvons l’activer, par contre elle ne fera rien… pour le moment !

Passons aux choses sérieuses, lors d’un développement nous faisons souvent appel aux mêmes choses, le dossier de l’extension, l’url vers le dossier de l’extension, la version de l’extension, le nom de l’option etc..

Les valeurs constantes

Nous ne voulons surtout pas redéfinir ce genre de choses et surtout que ces presque variables ne soient écrasées par inadvertance par sa propre extension ou celle d’un autre. Nous allons pour cela utiliser le « define » de PHP qui permet de créer une valeur constante qui ne peut être changée et qui est fixe, elle est surtout accessible depuis partout dans le code à partir du moment où elle est définie.

Nous allons donc créer nos valeurs définies juste au début de notre extension,  nous allons le préfixer par « ME », ce qui permettra à notre valeur d’être unique :

[pastacode provider= »manual » lang= »php »]


/*
Plugin Name: My extension
Plugin URI: http://nicolas-juen.fr
Description: Do soooooo much thing i can't tell you here...
Version: 1.0
Author: Rahe
Author URI: https://blog.nicolas-juen.fr
Text Domain: my-extension
Domain Path: languages
*/ 
define( 'ME_URL', plugin_dir_url ( __FILE__ ) ); 
define( 'ME_DIR', plugin_dir_path( __FILE__ ) ); 
define( 'ME_VERSION', '1.0' ); 
define( 'ME_OPTION', 'me_ext' );
[/pastacode]

Avec ces petites valeur définies, nous pourront y faire appel tout le long de notre extension et surtout un seul changement de celles-ci va être répercuté sur tout l'extension, donc pas de changements multiples à faire.

Les inclusions

Maintenant que nous avons ces petites constantes, nous allons pouvoir inclure les fichiers dont nous avons besoin, mais attention pas n'importe lesquels. Nous devons commencer par inclure nos fichiers indispensables comme par exemple les fichiers qui contiennent les fonctions utilisables partout ou notre classe client. Nous allons donc inclure nos fichiers en utilisant une petite fonction propre a chacune de vos extensions, elle va chercher dans vos dossiers la présence ou non des éléments et les inclure. [pastacode provider="manual" lang="php"]
// Function for easy load files
function _my_extension_load_files($dir, $files, $prefix = '') {
foreach ($files as $file) {
 if ( is_file($dir . $prefix . $file . ".php") ) {
 require_once($dir . $prefix . $file . ".php");
 }
 } 
}

// Les classes clientes
_my_extension_load_files( ME_DIR.'classes', array( 'main' ) );

// Les classes admin
_my_extension_load_files( ME_DIR.'classes/admin/', array( 'admin', 'page' ) );

// Les fonctions
_my_extension_load_files( ME_DIR.'functions/', array( 'plugin', 'tpl' ) );

[/pastacode]

L'activation, la désactivation et la désinstallation de l'extension

Lors de l'activation nous pouvons faire exécuter à WordPress une fonction, de même lors de la désactivation ou même lors de la suppression de notre extension.

[pastacode provider="manual" lang="php"]


// Activation, uninstall
register_activation_hook( __FILE__, 'MyExtension_Install' );
register_deactivation_hook ( __FILE__, 'MyExtension_Uninstall' );

[/pastacode]

Nous allons donc exécuter les fonctions ci-dessus lors de l'activation et de la désactivation de notre extension.

Dans ces fonctions nous pourrons par exemple créer une table ou alors créer une option si elle n'existe pas. Bref initialiser notre plugin ou bien préparer sa sortie en douceur.

L'initalisation

Nous avons donc nos fichiers inclus, et maintenant ? On ne peut pas tout lancer d'un coup sans se préoccuper de WordPress...

Nous allons donc nous caler au niveau de l'action "plugins_loaded" :

[pastacode provider="manual" lang="php"]



function MyExtension_Init() {
global $myExt;

// Load translations
load_plugin_textdomain ( 'my-extension', false, basename(rtrim(dirname(__FILE__), '/')) . '/languages' );

// Load client
$myExt['client'] = new myExtension_Client();

// Admin
if ( is_admin() ) {
$myExt['admin'] = new myExtension_Admin();
$myExt['admin_page'] = new myExtension_Admin_Page();

}
}
add_action( 'plugins_loaded', 'MyExtension_Init' );

[/pastacode]

Mais que faisons nous dans cette partie de l'extension ?

  1. Nous créons une global pour y stocker nos classes
  2. Nous mettons en place la traduction avec le slug 'my-extension'
  3. Nous instancions notre classe client
  4. Nous testons si nous sommes dans l'admin et c'est là que nous instancions notre classe admin.

Nous pourrions y faire d'autre choses, mais il vaut mieux les mettre dans nos classes admin ou client.

Voici le script final :

[pastacode provider="manual" lang="php"]



/*
Plugin Name: My extension
Plugin URI: http://nicolas-juen.fr
Description: Do soooooo much thing i can't tell you here...
Version: 1.0
Author: Rahe
Author URI: https://blog.nicolas-juen.fr
Text Domain: my-extension
Domain Path: languages
*/ 
define( 'ME_URL', plugin_dir_url ( __FILE__ ) ); 
define( 'ME_DIR', plugin_dir_path( __FILE__ ) ); 
define( 'ME_VERSION', '1.0' ); 
define( 'ME_OPTION', 'me_ext' );

// Activation, uninstall
register_activation_hook( __FILE__, 'MyExtension_Install' );
register_deactivation_hook ( __FILE__, 'MyExtension_Uninstall' );

function _my_extension_load_files($dir, $files, $prefix = '') {
foreach ($files as $file) {
 if ( is_file($dir . $prefix . $file . ".php") ) {
 require_once($dir . $prefix . $file . ".php");
 }
 } 
}

// Les classes clientes
_my_extension_load_files( ME_DIR.'classes', array( 'main' ) );

// Les classes admin
_my_extension_load_files( ME_DIR.'classes/admin/', array( 'admin', 'page' ) );

// Les fonctions
_my_extension_load_files( ME_DIR.'functions/', array( 'plugin', 'tpl' ) );

function MyExtension_Init() {
global $myExt;

// Load translations
load_plugin_textdomain ( 'my-extension', false, basename(rtrim(dirname(__FILE__), '/')) . '/languages' );

// Load client
$myExt['client'] = new myExtension_Client();

// Admin
if ( is_admin() ) {
$myExt['admin'] = new myExtension_Admin();
$myExt['admin_page'] = new myExtension_Admin_Page();

}
}

[/pastacode]

A partir de là, à vous de construire vos méthodes, vos classes etc...

L'internationalisation

N'oubliez pas que vos plugins peuvent être utilisés partout dans le monde et donc chacun va vouloir retrouver son interface dans la langue de son site. Vous avez pu voir que dans le plugin on charge les fichiers de traduction. Chaque fichier de traduction est propre à la langue et reprend le schéma 'slug-{locale}'.po/mo. Ils sont stockés, dans notre cas, dans le dossier languages de note plugin mais ils peuvent être ailleurs aussi.

Pensez bien que pour rester dans les règles avec WordPress il faut que le slug de traduction(ou domaine) soit le même que le dossier dans lequel se trouve votre extension ou le nom du fichier, ici ce serait 'my-extension'. WordPress a comme objectif de ne plus embarquer les traductions dans les plugins mais bient avoir une base générale des plugins et thèmes avec leurs fichiers de traduction disponibles et de télécharger à la demande les bons fichiers. Ce qui éviterait d'avoir en plus de sa langue les 45 autres fichiers des autres langues en téléchargeant un plugin.

Otto(core dev) l'explique très bien dans son article sur le futur de l'internationalisation dans WordPress.

 

Conclusion

Il faut toujours garder à l'esprit qu'il ne faut pas tout réinventer, WordPress dispose de hook de type actions ou de type filtre qui sont disséminés un peu partout dans WordPress, à vous de les débusquer et de les utiliser au meilleur moment.

Pensez aussi contexte, puis-je faire cette action n'importe quand ? est-ce que j'ai besoin d'inclure ce fichier javascript/css partout dans l'administration/ le front ?

Une extension bien construite est surtout une extension qui respecte WordPress, les utilisateurs et la sécurité.

Sachez que cet exemple de starter kit est pris depuis la base WordPress plugin del'agence dans laquelle je travaille, BeApi, et accessible sur github.

7 thoughts on “Créer une extension WordPress : Les premières étapes

  1. Excellent tutoriel.
    Je voudrais mettre du javascript dans mon plugin. Je ne comprends pas où placer l’inclusion du fichier .js
    Est-ce au début de my-extension.php ?
    Mais dans ce cas, elle n’est pas placée au début de
    wp-admin/admin.php?page=my-extension/my-extension.php
    Je suis un peu perdu…..
    Merci !

  2. Bonjour j’aimerais savoir comment ajouter

    via le plugin et votre dossier pre construit

    un fichier bbcs.css qui se trouve dans \footerbar_bcs\ressources\css\bbcs.css

    et du code html (div… contenant le menu name: mmobilebcs horizontallement)

    qui dois se placer directement apres le de toute les pages mais qu’a une seul condition que la la page afficher soit max 740px (thème responsive)?

    Je cherche a créer ceci: en pluging http://www.bcselect.fr/menu.jpg

    MErci d’avance

  3. bonjour,
    j’aimerais savoir comment ajouter dans la page d’accueil du plugin ( créée par la méthode add_menu_page…), un lien qui point vers une autre page dans le même plugin.
    par exemple j’ai un tableau dans la page par défaut de plugin et dans ce tableau un href pour afficher les details.
    merci d’avance

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.