Un plugin WordPress peut faire appel à de nombreuses class
qu’il faudra inclure via autant de require
ou include
. C’est long, fastidieux et potentiellement source d’erreurs. Pourquoi s’embêter avec ça quand PHP peut le faire pour nous ?
Les conventions
En bon codeur respecteux des standards, on part du principe que toutes nos class
sont regroupées dans un même dossier et que les fichiers sont nommés selon ce modèle : class-nomdemaclass.php
Si toutes nos class sont regroupées dans un dossier includes
, on obtient quelque chose ressemblant à ceci :
L’autoloader
Nous allons créer notre autoloader. Et vous savez quoi ? Ce sera lui aussi une… class
. Dans le dossier includes
de notre plugin, on crée un fichier class-rrphf-myplugin-autoloader.php
et on y rédige le code suivant :
<?php defined( 'ABSPATH' ) || exit; /** * Project: RRPhF MyPlugin * File: class-rrphf-myplugin-autoloader.php * User: reskator * Author: RR PhF * * @Description Class autoloader for RRPhF MyPlugin plugin * @since 1.0.0 */ if ( ! class_exists( 'RRPhF_MyPlugin_autoloader' ) ) : class RRPhF_MyPlugin_autoloader { /** * Singleton * * @var null Single instance */ private static $_instance = null; /** * RRPhF_MyPlugin_autoloader constructor. * */ private function __construct() { spl_autoload_register( [$this, 'load'] ); } /** * Singleton method * * If it has not already been done, creates and return an instance of the class * * @author RR PhF * @since 1.0.0 * * @static * @return \RRPhF_MyPlugin_autoloader */ public static function get_instance() { if ( ! self::$_instance ) { self::$_instance = new self(); } return self::$_instance; } /** * Class loader * * Converts the name of the class to a file name and includes the class file. * * @author RR PhF * @since 1.0.0 * * @param string $class_name - class to load */ public function load( $class_name ) { //Converts the class name to a file name $class_file = str_replace( '_', '-', strtolower( $class_name ) ); $class_file = 'class-' . $class_file; $class_file = __DIR__ . '/' . $class_file; // do the autoloading spl_autoload( $class_file, '.php' ); } } /** * Make sure an instance can't be cloned * * @author RR PhF * @since 1.0.0 * */ private function __clone() { // do nothing } } RRPhF_MyPlugin_autoloader::get_instance(); endif;
Notre class est instanciée à la ligne 81.
par l’appel de la méthode… get_intance()
RRPhF_MyPlugin_autoloader::get_instance();
Le fait d’instancier la class fait que PHP cherche si un constructeur est présent dans la class et l’exécute automatiquement. Ça tombe bien notre class en comporte un :
private function __construct() { spl_autoload_register( [$this, 'load'] ); }
Pour schématiser, spl_autoload_register()
permet d’indiquer à PHP la fonction (méthode) qu’il devra utiliser lorsqu’il découvrira une nouvelle class durant l’exécution de notre plugin. En bonus, il se chargera de transmettre à notre méthode le nom de la class concernée. Dans le cas présent, comme vous pouvez le voir, nous lui indiquons d’utiliser la méthode load
:
*/ public function load( $class_name ) { //Converts the class name to a file name $class_file = str_replace( '_', '-', strtolower( $class_name ) ); $class_file = 'class-'. $class_file; $class_file = __DIR__ .'/'. $class_file; // do the autoloading spl_autoload( $class_file, '.php' ); }
La méthode load
dispose de l’argument $class_name
. C’est cet argument qui reçoit le nom de la class ayant déclenché l’appel _autoload. Après avoir converti le nom de la class en nom de fichier (mais sans l’extension), on appelle la méthode PHP spl_autoload()
avec, en 1er argument, le path du fichier à charger (toujours sans l’extension), et en deuxième argument, l’extension. Notez que notre class est particulièrement ‘verrouillée’ :
- la propriété
$_instance
est déclaréeprivate
etstatic
; - le
__constructor
est déclaréprivate
; - et
get_instance()
fait sont possible pour ne déclarer qu’une instance.
Je dis qu’il fait son possible car il ne peut empêcher que l’instance soit… clonée :/ D’où la dernière méthode de notre class :
private function __clone() { // do nothing }
Dans le cas où l’on tenterait de cloner l’instance de cette class, la méthode __clone() sera appelée… mais ne fera rien : plus de clonage possible.
Implémenter notre autoloader
L’autoloader étant en place, il nous faut l’implémenter dans notre plugin :
<?php defined( 'ABSPATH' ) || exit; /* Plugin Name: RRPhF MyPlugin Plugin URI: https://www.reskator.fr Description: The best plugin in the world that everyone expected Version: 1.0.0 Author: Reskator Author URI: https://www.reskator.fr Text Domain: rrphfmyplugin Domain Path: /languages License: GPLv2 or later */ if ( ! defined( 'RRPHF_MYPLUGIN_FILE' ) ) { define( 'RRPHF_MYPLUGIN_FILE', __FILE__ ); } if ( ! class_exists( 'RRPhFMyPlugin_autoloader' ) ) { include_once __DIR__ .'/includes/class-rrphfmyplugin-autoloader.php'; } // Calls plugin's main class $myplugin = new RRPhF_MyPlugin();
Et voilà ! On n’a désormais qu’un seul et unique include pour charger toutes nos class :) Et on peux voir la ‘magie’ opérer dès l’instruction suivante qui instancie la class principale du plugin. Sans autoloader, on a tendance à inclure TOUTES les class. Or, il se peut qu’elles ne soient pas toutes requises à chaque fois. Avec un autoloader, PHP ne chargera que les class nécessaires, libérant ainsi des ressources (mémoire, accès disques, etc.).
Commentaires récents