Créer une extension WordPress : Les premières étapes
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
- inc – 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
- class.client.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.
- class.admin.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.
- class.admin.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.
- functions.tpl.php – dans ce fichier vous pourrez mettre les fonctions que l’on appelle depuis de thème.
- ressources – 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 :
1 2 3 4 5 6 7 8 | /* 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: http://blog.nicolas-juen.fr */ |
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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* 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: http://blog.nicolas-juen.fr */ define( 'ME_URL', plugins_url('/', __FILE__) ); define( 'ME_DIR', dirname(__FILE__) ); define( 'ME_VERSION', '1.0' ); define( 'ME_OPTION', 'me_ext' ); |
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 de la manière suivante :
1 2 3 | require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.client.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'functions.plugin.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'functions.tpl.php' ); |
Je n’ai sciemment inclus le fichier d’admin car nous ne le ferons que quand nous serons dans l’administration, mais là nous ne pouvons pas encore le savoir.
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.
1 2 3 | // Activation, uninstall register_activation_hook( __FILE__, 'MyExtension_Install' ); register_deactivation_hook ( __FILE__, 'MyExtension_Uninstall' ); |
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 » :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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() ) { require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.admin.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.admin.page.php' ); $myExt['admin'] = new myExtension_Admin(); $myExt['admin_page'] = new myExtension_Admin_Page(); } } add_action( 'plugins_loaded', 'MyExtension_Init' ); |
Mais que faisons nous dans cette partie de l’extension ?
- Nous créons une global pour y stocker nos classes
- Nous mettons en place la traduction avec le slug ‘my-extension’
- Nous instancions notre classe client
- Nous testons si nous sommes dans l’admin et c’est là que nous incluons notre fichier admin et aussi 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* 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: http://blog.nicolas-juen.fr */define( 'ME_URL', plugins_url('/', __FILE__) ); define( 'ME_DIR', dirname(__FILE__) ); define( 'ME_VERSION', '1.0' ); define( 'ME_OPTION', 'me_ext' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.client.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'functions.plugin.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'functions.tpl.php' ); // Activation, uninstall register_activation_hook( __FILE__, 'MyExtension_Install' ); register_deactivation_hook ( __FILE__, 'MyExtension_Uninstall' ); 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() ) { require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.admin.php' ); require_once( ME_DIR . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'class.admin.page.php' ); $myExt['admin'] = new myExtension_Admin(); $myExt['admin_page'] = new myExtension_Admin_Page(); } } |
A partir de là, à vous de construire vos méthodes, vos classes etc…
Vous pouvez télécharger le tout ici
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é.
