{"id":1889,"date":"2018-11-02T15:08:51","date_gmt":"2018-11-02T15:08:51","guid":{"rendered":"https:\/\/reskator.fr\/?p=1889"},"modified":"2021-01-14T10:56:09","modified_gmt":"2021-01-14T10:56:09","slug":"autoload-pour-plugin-wordpress","status":"publish","type":"post","link":"https:\/\/dev9.reskator.fr\/cms\/2018\/autoload-pour-plugin-wordpress\/","title":{"rendered":"Un autoload pour plugin WordPress"},"content":{"rendered":"\n<p class=\"has-drop-cap has-background\" style=\"background-color:#f5f6f7\" data-block-type=\"core\">Un plugin WordPress peut faire appel \u00e0 de nombreuses <code>class<\/code> qu\u2019il faudra inclure via autant de <code>require<\/code> ou <code>include<\/code>. C\u2019est long, fastidieux et potentiellement source d'erreurs. Pourquoi s\u2019emb\u00eater avec \u00e7a quand PHP peut le faire pour nous&nbsp;?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" data-block-type=\"core\">Les conventions<\/h2>\n\n\n\n<p data-block-type=\"core\">En bon codeur respecteux des standards, on part du principe que toutes nos <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">class<\/code> sont regroup\u00e9es dans un m\u00eame dossier et que les fichiers sont nomm\u00e9s selon ce mod\u00e8le&nbsp;: <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">class-nomdemaclass.php<\/code> Si toutes nos class sont regroup\u00e9es dans un dossier <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">includes<\/code>, on obtient quelque chose ressemblant \u00e0 ceci :<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\" data-block-type=\"core\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2020\/12\/arborescence-class-300x300-1.png\" alt=\"\" class=\"wp-image-45351\" srcset=\"https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2020\/12\/arborescence-class-300x300-1.png 300w, https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2020\/12\/arborescence-class-300x300-1-150x150.png 150w, https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2020\/12\/arborescence-class-300x300-1-100x100.png 100w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" data-block-type=\"core\">L\u2019autoloader<\/h2>\n\n\n\n<p data-block-type=\"core\">Nous allons cr\u00e9er notre autoloader. Et vous savez quoi ? Ce sera lui aussi une\u2026 <code data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">class<\/code>. Dans le dossier <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">includes<\/code>&nbsp;de notre plugin, on cr\u00e9e un fichier <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">class-rrphf-myplugin-autoloader.php<\/code>&nbsp;et on y r\u00e9dige le code suivant :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"wp-content\/plugins\/rrphf-myplugin\/includes\/class-rrphf-myplugin-autoloader.php\" data-enlighter-group=\"Autoloader\">&lt;?php defined( 'ABSPATH' ) || exit;\n\/**\n * Project: RRPhF MyPlugin\n * File: class-rrphf-myplugin-autoloader.php\n * User: reskator\n * Author: RR PhF\n *\n * @Description Class autoloader for RRPhF MyPlugin plugin\n * @since        1.0.0\n *\/\n\nif ( ! class_exists( 'RRPhF_MyPlugin_autoloader' ) ) :\n   class RRPhF_MyPlugin_autoloader {\n      \/**\n       * Singleton\n       *\n       * @var null Single instance\n       *\/\n      private static $_instance = null;\n      \n      \/**\n       * RRPhF_MyPlugin_autoloader constructor.\n       *\n       *\/\n      private function __construct() {\n         spl_autoload_register( [$this, 'load'] );\n      }\n      \n      \/**\n       * Singleton method\n       * \n       * If it has not already been done, creates and return an instance of the class\n       *\n       * @author RR PhF\n       * @since  1.0.0\n       *\n       * @static\n       * @return \\RRPhF_MyPlugin_autoloader\n       *\/\n      public static function get_instance() {\n         if ( ! self::$_instance ) {\n            self::$_instance = new self();\n         }\n         \n         return self::$_instance;\n      }\n      \n      \/**\n       * Class loader\n       *\n       * Converts the name of the class to a file name and includes the class file.\n       *\n       * @author RR PhF\n       * @since  1.0.0\n       *\n       * @param string $class_name - class to load\n       *\/\n      public function load( $class_name ) {\n         \/\/Converts the class name to a file name\n         $class_file = str_replace( '_', '-', strtolower( $class_name ) );\n         $class_file = 'class-' . $class_file;\n         $class_file = __DIR__ . '\/' . $class_file;\n         \n         \/\/ do the autoloading\n         spl_autoload( $class_file, '.php' );\n         }\n      }\n      \n      \/**\n       * Make sure an instance can't be cloned\n       *\n       * @author RR PhF\n       * @since  1.0.0\n       *\n       *\/\n      private function __clone() {\n         \/\/ do nothing\n      }\n   }\n   \n   RRPhF_MyPlugin_autoloader::get_instance();\n\nendif;\n<\/pre>\n\n\n\n<p data-block-type=\"core\">Notre class est instanci\u00e9e \u00e0 la ligne <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">81.<\/code> par l'appel de la m\u00e9thode\u2026 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">get_intance()<\/code><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"\" data-enlighter-theme=\"\" data-enlighter-highlight=\"81\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"81\" data-enlighter-title=\"\" data-enlighter-group=\"\">RRPhF_MyPlugin_autoloader::get_instance();<\/pre>\n\n\n\n<p data-block-type=\"core\">Le fait d'instancier la class fait que PHP cherche si un constructeur est pr\u00e9sent dans la class et l'ex\u00e9cute automatiquement. \u00c7a tombe bien notre class en comporte un :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"28-30\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"28\" data-enlighter-title=\"\" data-enlighter-group=\"\">private function __construct() {\n      spl_autoload_register( [$this, 'load'] );\n}<\/pre>\n\n\n\n<p data-block-type=\"core\">Pour sch\u00e9matiser, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">spl_autoload_register()<\/code> permet d'indiquer \u00e0 PHP la fonction (m\u00e9thode) qu'il devra utiliser lorsqu'il d\u00e9couvrira une nouvelle class durant l'ex\u00e9cution de notre plugin. En bonus, il se chargera de transmettre \u00e0 notre m\u00e9thode le nom de la class concern\u00e9e. Dans le cas pr\u00e9sent, comme vous pouvez le voir, nous lui indiquons d\u2019utiliser la m\u00e9thode&nbsp;<code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">load<\/code> :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"59-69\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"58\" data-enlighter-title=\"\" data-enlighter-group=\"\">   *\/\n  public function load( $class_name ) {\n    \/\/Converts the class name to a file name\n    $class_file = str_replace( '_', '-', strtolower( $class_name ) );\n    $class_file = 'class-'. $class_file;\n    $class_file = __DIR__ .'\/'. $class_file;\n    \n    \/\/ do the autoloading\n    spl_autoload( $class_file, '.php' );\n  }\n<\/pre>\n\n\n\n<p data-block-type=\"core\">La m\u00e9thode <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">load<\/code> dispose de l'argument <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">$class_name<\/code>. C'est cet argument qui re\u00e7oit le nom de la class ayant d\u00e9clench\u00e9 l'appel _autoload. Apr\u00e8s avoir converti le nom de la class en nom de fichier (<em>mais sans l'extension<\/em>), on appelle la m\u00e9thode PHP <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">spl_autoload()<\/code> avec, en 1er argument, le path du fichier \u00e0 charger (<em>toujours sans l'extension<\/em>), et en deuxi\u00e8me argument, l'extension. Notez que notre class est particuli\u00e8rement \u2018verrouill\u00e9e\u2019 :<\/p>\n\n\n\n<ul class=\"wp-block-list\" data-block-type=\"core\"><li>la propri\u00e9t\u00e9 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">$_instance<\/code> est d\u00e9clar\u00e9e <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">private<\/code> et <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">static<\/code> ;<\/li><li>le <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">__constructor<\/code> est d\u00e9clar\u00e9 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">private<\/code> ;<\/li><li>et <code class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">get_instance()<\/code> fait sont possible pour ne d\u00e9clarer qu'une instance.<\/li><\/ul>\n\n\n\n<p data-block-type=\"core\">Je dis qu'il fait son possible car il ne peut emp\u00eacher que l'instance soit\u2026 clon\u00e9e :\/ D'o\u00f9 la derni\u00e8re m\u00e9thode de notre class :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"76\" data-enlighter-title=\"\" data-enlighter-group=\"\">private function __clone() {\n   \/\/ do nothing\n}\n<\/pre>\n\n\n\n<p data-block-type=\"core\">Dans le cas o\u00f9 l'on tenterait de cloner l'instance de cette class, la m\u00e9thode __clone() sera appel\u00e9e\u2026 mais ne fera rien : plus de clonage possible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" data-block-type=\"core\">Impl\u00e9menter notre autoloader<\/h2>\n\n\n\n<p data-block-type=\"core\">L'autoloader \u00e9tant en place, il nous faut l'impl\u00e9menter dans notre plugin :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"\" data-enlighter-theme=\"\" data-enlighter-highlight=\"19\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"wp-content\/plugins\/rrphf-myplugin\/rrphf-myplugin.php\" data-enlighter-group=\"MyPlugin\">&lt;?php defined( 'ABSPATH' ) || exit;\n\/*\nPlugin Name: RRPhF MyPlugin\nPlugin URI: https:\/\/www.reskator.fr\nDescription: The best plugin in the world that everyone expected\nVersion: 1.0.0\nAuthor: Reskator\nAuthor URI: https:\/\/www.reskator.fr\nText Domain: rrphfmyplugin\nDomain Path: \/languages\nLicense: GPLv2 or later\n*\/\n\nif ( ! defined( 'RRPHF_MYPLUGIN_FILE' ) ) {\n   define( 'RRPHF_MYPLUGIN_FILE', __FILE__ );\n}\n\nif ( ! class_exists( 'RRPhFMyPlugin_autoloader' ) ) {\n   include_once __DIR__ .'\/includes\/class-rrphfmyplugin-autoloader.php';\n}\n\n\/\/ Calls plugin's main class\n$myplugin = new RRPhF_MyPlugin();<\/pre>\n\n\n\n<p data-block-type=\"core\">Et voil\u00e0 ! On n'a d\u00e9sormais qu'un seul et unique include pour charger toutes nos class \ud83d\ude42 Et on peux voir la 'magie' op\u00e9rer d\u00e8s l'instruction suivante qui instancie la class principale du plugin. Sans autoloader, on a tendance \u00e0 inclure TOUTES les class. Or, il se peut qu'elles ne soient pas toutes requises \u00e0 chaque fois. Avec un autoloader, PHP ne chargera que les class n\u00e9cessaires, lib\u00e9rant ainsi des ressources (m\u00e9moire, acc\u00e8s disques, etc.).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-color-1-background-color has-color-1-color is-style-dots\"\/ data-block-type=\"core\">\n","protected":false},"excerpt":{"rendered":"<p>Un plugin WordPress peut faire appel \u00e0 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\u00eater avec \u00e7a quand PHP peut le faire pour nous\u00a0? <\/p>\n","protected":false},"author":3,"featured_media":45352,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,3],"tags":[],"class_list":["post-1889","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developpeur","category-php"],"featured_image_urls_v2":{"full":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding.png",1353,885,false],"thumbnail":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding-150x150.png",150,150,true],"medium":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding-300x196.png",300,196,true],"medium_large":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding-768x502.png",768,502,true],"large":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding-1024x670.png",1024,670,true],"1536x1536":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding.png",1353,885,false],"2048x2048":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding.png",1353,885,false],"acf-gallery":["https:\/\/dev9.reskator.fr\/cms\/wp-content\/uploads\/2018\/11\/phpstorm-coding-300x300.png",300,300,true]},"post_excerpt_stackable_v2":"<p>Un plugin WordPress peut faire appel \u00e0 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\u00eater avec \u00e7a quand PHP peut le faire pour nous\u00a0? <\/p>\n","category_list_v2":"<a href=\"https:\/\/dev9.reskator.fr\/cms\/category\/developpeur\/\" rel=\"category tag\">D\u00e9veloppeur<\/a>, <a href=\"https:\/\/dev9.reskator.fr\/cms\/category\/developpeur\/php\/\" rel=\"category tag\">PHP<\/a>","author_info_v2":{"name":"Philippe Reskator","url":"https:\/\/dev9.reskator.fr\/cms\/author\/philippe\/"},"comments_num_v2":"0 commentaire","_links":{"self":[{"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/posts\/1889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/comments?post=1889"}],"version-history":[{"count":0,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/posts\/1889\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/media\/45352"}],"wp:attachment":[{"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/media?parent=1889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/categories?post=1889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev9.reskator.fr\/cms\/wp-json\/wp\/v2\/tags?post=1889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}