Vous êtes sur la page 1sur 10

Autochargement de classes en PHP

par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)
Date de publication : 20/03/2012 Dernire mise jour :

L'auto-chargement de classes est une fonctionnalit apparue avec PHP5.0. Nous allons ici dtailler son fonctionnement, ses diffrentes implmentations, puis prsenter des solutions dveloppes dans les frameworks modernes.

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

I - Introduction..............................................................................................................................................................3 II - PHP et autoload.....................................................................................................................................................4 II-A - Pourquoi auto-charger ?............................................................................................................................... 4 II-B - La solution __autoload()............................................................................................................................... 4 II-C - SPL en renfort.............................................................................................................................................. 5 III - Autoloaders reconnus........................................................................................................................................... 7 III-A - Zend Framework 1.......................................................................................................................................7 III-B - Symfony2......................................................................................................................................................7 III-C - Doctrine2...................................................................................................................................................... 8 III-D - PSR-0...........................................................................................................................................................8 IV - Conclusions.........................................................................................................................................................10

-2Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

I - Introduction
Dans le pass, l'autoload a t dcri pour ses impacts sur les performances par rapport des appels require_once classiques. Cependant, PHP5.2 a chang la donne, car il inclut un important mcanisme de cache des appels systmes (realpath et stat). De plus, dans de gros frameworks comme ZendFramework ou Symfony, il y a souvent des classes qui vont charger des dpendances (d'autres classes) qui ne seront somme toute peut-tre pas utilises rellement par l'application. Il en rsulte une somme de code importante charger par l'analyseur lexical/syntaxique de PHP (compilation) et les require_once utilisent des appels systme stat chaque invocation, ce qui peut rapidement ralentir le systme. L'autoload, lui, n'est invoqu que lorsqu'il est ncessaire, et si le chargement de la classe a dja t effectu, il "saute son tour" et vite de couteux appels si require_once n'est pas utilis. Autre raison: utiliser l'autoload permet d'abstraire le lieu de rsidence des classes dans le projet. Dans beaucoup de projets PHP, il y a de complexes systmes de mapping des classes vers les fichiers, comme par exemple des modifications de l'include_path, ou encore des astuces reposant sur __DIR__.

-3Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

II - PHP et autoload II-A - Pourquoi auto-charger ?


Auto-charger une classe, c'est simplement faire en sorte que l'appel une classe puisse se faire alors que PHP ne connait pas encore sa dfinition. Comme PHP n'est pas devin ni magicien, il lui faut la dfinition de cette classe. 2 solutions : 1 2 Faire charger manuellement la classe PHP, en incluant sa dfinition avant tout appel celle-ci ; Faire charger automatiquement la classe par PHP, en lui indiquant partir de son nom, comment trouver le fichier dans lequel sa dfinition rside.

Manuellement, c'est simple: un appel require ou include (en gnral, on utilise les variantes _once pour tre sr que la classe n'est pas charge 2 fois ce qui reprsente une fatal error en PHP). Le problme du chargement manuel est assez simple: c'est pnible, et lorsqu'il y a beaucoup de classes, notamment des classes en incluant d'autres, il faut tre sr que tout le code sera utilis au risque de faire charger PHP des fichiers pour rien, ce qui est une opration lourde sur les grosses applications et mne rapidement des problmes de performance. Vient alors le chargement automatique, dont le concept est des plus simples: fournir une rgle de transformation qui permettra PHP partir du nom de la classe (non trouve) de dduire un fichier (et son chemin) inclure, dans lequel il devra alors la trouver sous peine de fatal error.

II-B - La solution __autoload()


La fonction magique __autoload() permet d'indiquer PHP une fonction qu'il devra utiliser pour convertir le nom de la classe charger, en nom (et chemin) de fichier. La fonction prend en paramtre le nom de la classe que PHP lui passera (sous forme de chaine), et devra alors crire une rgle qui permettra d'inclure le fichier dans lequel se trouve la classe charger. Ainsi, tous les noms de classe devront respecter une rgle commune, et les fichiers devront tre logs un endroit prcis. exemple d'utilisation de la fonction __autoload()

<?php function __autoload($class) { static $classDir = '/var/lib/php/classes'; $file = str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')) . '.php'; require "$classDir/$file"; } // Appel une classe inconnue, la fonction __autoload() est invoque automatiquement JP\Foo\Dvp::someMethod(); /* le fichier /var/lib/php/classes/JP/Foo/Dvp.php a t inclus, on suppose qu'il existait */ /* La dfinition de la classe doit se trouver dans ce fichier, sinon PHP renverra une erreur fatale */

Cette rgle de translation des "\" reprsentant le sparateur de namespaces en PHP, par des "/"; est trs connue dans le monde PHP. L'ancienne notation (avant PHP5.3) utilisait l'underscore _ comme sparateur, plutt que l'anti-slash. Aujourd'hui, les autoloaders sont compatibles avec les 2 syntaxes. __autoload() n'est utilise que si PHP ne connait pas la classe ds qu'il la rencontre, l'excution. L'inclusion dans la fonction __autoload() doit russir, sinon une fatal error PHP sera leve. La classe en question doit se trouver dans le fichier charg, sinon une fatal error PHP sera leve.
-4Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

__autoload() possde 2 problmes: il n'est pas possible de dclarer 2 fois cette fonction. Ainsi, TOUTES les classes doivent obir UNE et mme rgle de nommage. Sur des grandes applications, ou des applications complexes, c'est trs contraignant respecter. Aussi, __autoload() est une fonction, on ne peut pas spcifier une mthode d'une classe, ce qui en design objet reprsente un inconvnient.

II-C - SPL en renfort


La SPL (Standard PHP Library) arrive alors en renfort avec ses fonctions spl_autoload_*(). Les nouveauts: les fonctions SPL permettent de grer plusieurs fonctions d'autoload, de grer des extensions de fichiers, ou encore l'utilisation d'une mthode de classe plutt qu'une fonction. Les fonctions anonymes sont aussi utilisables. spl_autoload_register(), permet d'enregistrer une fonction sur la pile des autoloads (on notera donc aussi spl_autoload_unregister()). spl_autoload_functions() retourne les fonctions actuellement enregistres sur la pile. exemple spl_autoload_register()
<?php class Loader { const CLASS_DIR = '/var/lib/php/classes'; public static function loader2($class) { $file = str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class,'\\')) . '.php'; require $file; } } spl_autoload_register(function($class) {include $class . '.php'; }); spl_autoload_register(array('Loader','loader2')); $a = new Jp\Devp\Code();

La cration de l'objet $a va faire passer PHP dans la fonction anonyme d'abord, puis loader2() (sous forme de mthode de classe) si la premire n'a pas russi. Comme nous utilisons include et non require, si le fichier n'est pas trouv, un warning sera mis et PHP continuera. Enfin, s'il n'a pas trouv la classe, alors il va renvoyer une fatal error car cette classe est introuvable. Vous pouvez aussi essayer les fonctions d'autoload grce spl_autoload_call() essai des fonctions d'autoload prcedemment enregistres
// ... if (spl_autoload_call('Jp\Devp\Code')) { echo "classe charge"; }

Attention certaines fonctions comme class_exists(). Son deuxime paramtre, boolen 'use_autoload' est true par dfaut. fonction utilisant l'autoload
if (class_exists('Ma\Classe')) { // ... ... }

Un appel comme celui-ci utilisera l'autoload pour chercher Ma\Classe si celle-ci n'existait pas lors de l'appel. Les frameworks sont des ensembles de classes, de beaucoup de classes... Ds lors, une mauvaise rgle d'autoload peut avoir un impact sur les performances et sur la structure du framework.

-5Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

L'autoload n'est pas sans problme, d'autant plus qu'on doit pouvoir utiliser plusieurs fonctions d'autoload en harmonie. Dans la mesure du possible, incluez dans votre fonction d'autoload un chemin complet vers un fichier de classe, comme par exemple /var/lib/php/classes/Foo.php Le fait d'utiliser avec require/include un chemin "fantme", comme par exemple "Bar/ Foo.php" ou encore tout simplement "Foo.php", fera scanner tout l'include_path par PHP, la recherche de votre fichier. Non seulement ceci peut avoir un impact sur les performances (surtout dans le pire des cas, le chemin effectif apparait en dernier), mais aussi cela vous obligera jongler avec une directive de configuration de PHP, et compliquera le dploiement de vos applications.

-6Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

III - Autoloaders reconnus


Aujourd'hui, on ne rinvente plus beaucoup la roue en matire d'auto-chargement de classes en PHP. Tous les frameworks incluent un autoloader, qui respecte certaines conventions. Pour viter que ces conventions soient diffrentes entre chaque framework, et que chacun oblige ses utilisateurs fonctionner d'une certaine manire bien lui, un mouvement "officiel" de convention est n en 2009, en mme temps que l'apparition de PHP5.3 et du concept de namespaces. Ce mouvement s'appelle "PSR-0", il est dtaill dans les chapitres suivants. En attendant, voyons quelques implmentations d'autoload PHP.

III-A - Zend Framework 1


ZendFramework 1 utilise l'ancienne syntaxe PHP5.2 avec des underscores. Zend_Loader_Autoloader. Les buts de ce composant sont les suivants : 1 2 3 4 5 Il propose la classe

Proposer une gestion interne d'espaces de nommage. Si le prfixe de la classe n'est pas dans la liste des espaces enregistrs, retourner false immdiatement. Proposer un auto-chargement par dfaut. Dans le cas d'quipes trs rparties ou utilisant des espaces de nommage non determins l'avance, l'autoload doit pouvoir tre configur pour capter n'importe quel espace de nom. Proposer de supprimer la dtection d'erreurs. La suppression d'erreur est une mauvaise ide. C'est coteux pour PHP, et cela masque les problmes rels. Le mcanisme de suppression d'erreur est par dfaut dsactiv, mais peut tre activ la demande. Autoriser le dveloppeur utiliser son propre mcanisme d'autoload. Certains ne veulent pas de l'implmentation interne Zend_Loader::loadClass() pour l'auto-chargement, il est donc possible de spcifier sa fonction personnalise. Autoriser la manipulation de la chaine de fonctions de spl_autoload(). L'ide est de permettre de manipuler la pile des autoloads, par exemple insrer des chargeurs de ressources n'ayant pas de relation 1-1 avec les dossiers, avant ou aprs l'autoload par dfaut de ZF.

Ce dernier point est intressant car il permet d'avoir des arborescences dont les noms de classes ne sont plus directement attachs au systme de fichiers :
. |-| |-| | | |

forms `-- Guestbook.php models |-- DbTable | `-- Guestbook.php |-- Guestbook.php `-- GuestbookMapper.php

// Foo_Form_Guestbook // Foo_Model_DbTable_Guestbook // Foo_Model_Guestbook // Foo_Model_GuestbookMapper

III-B - Symfony2
L'autoloader de Symfony2 est plus rcent que celui de ZendFramework1 (forcment), et est compatible avec les anciennes normes (sparateur _) et les nouvelles ( sparateur \). Il est partiellement compatible PSR-0 et peut ventuellement se reposer sur l'include_path de PHP. Exemple d'utilisation de l'autoloader Symfony2
<?php require_once '/path/to/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; use Symfony\Component\ClassLoader\UniversalClassLoader; define ('CLASS_PATH', '/var/lib/php/classes');

-7Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

Exemple d'utilisation de l'autoloader Symfony2

$loader = new UniversalClassLoader(); $loader->registerNamespaces(array( 'Symfony' => CLASS_PATH.'/vendor/symfony/src', 'Monolog' => CLASS_PATH.'/vendor/monolog/src', )); /* active spl_autoload_register() */ $loader->register(); /* Charge /var/lib/php/classes/vendor/symfony/src/Symfony/Foo/Bar.php */ $s = new Symfony\Foo\Bar;

Symfony2 est conscient des problmes de performances, et propose deux autres implmentations d'auto-chargement bases sur UniversalClassLoader : ApcUniversalClassLoader et ClassCollectionLoader.

III-C - Doctrine2
L'autoloader de Doctrine2 est simple et efficace. Il n'est pas 100% compatible PSR-0, mais s'en rapproche beaucoup. Voici des exemples d'utilisation : Exemple d'utilisation de l'autoloader de Doctrine 2

<?php define ('CLASS_PATH', '/var/lib/php/classes'); use Doctrine\Common\ClassLoader; require '/path/to/Doctrine/Common/ClassLoader.php'; $ormLoader = new ClassLoader('Doctrine\ORM', CLASS_PATH . '/orm'); $ormLoader->register(); $myLoader = new ClassLoader('JP', CLASS_PATH . '/JP/myproject/lib'); $myLoader->setNamespaceSeparator('_'); $myLoader->register(); $jp = new JP_Foo_Bar; /* charge /var/lib/php/classes/JP/myproject/lib/JP/Foo/Bar.php */ $orm = new Doctrine\ORM\Foo\Baz; /* charge /var/lib/php/classes/orm/Doctrine/ORM/Foo/Baz.php */

Le principe ici est d'utiliser un objet ClassLoader par type de namespace que l'on veut charger. L'autoloader utilise par dfaut '\' comme sparateur, mais on peut le changer, en '_' par exemple. Il propose aussi des mthodes comme canLoadClass() ou classExists(). Sa documentation vous en apprendra plus.

III-D - PSR-0
La grande majorit des professionnels du web et du langage PHP se sont mis d'accord sur la manire d'autocharger les classes, surtout dans la structure des fichiers et le nom des classes et namespaces. Ils ont tabli une norme, ou plutt un accord que tout le monde est sens respecter. Il s'agit de PSR-O. Cet accord est crit noir sur blanc l'adresse https://github.com/php-fig/fig-standards/blob/master/accepted/ PSR-0.md, nous allons ici rpter les grandes lignes :

Recommandations PSR-0

Un nom pleinement qualifi doit avoir la structure suivante : \<Vendor Name>\(<Namespace>\)*<Class Name> Chaque namespace doit avoir un namespace de haut niveau ("Vendor Name"). Chaque namespace peut avoir autant de sous-namespaces qu'il le souhaite. Chaque sparateur de namespace est converti en DIRECTORY_SEPARATOR lors du chargement depuis le systme de fichiers.

-8Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

Chaque "_" dans CLASS NAME est convertis vers DIRECTORY_SEPARATOR. Le caractre "_" est ignor lorsque plac dans le namespace. Le nom pleinement qualifi est suffix de '.php' lors du chargement depuis le systme de fichiers. Les noms de vendor, nampespace et classes peuvent contenir tout type de lettres, majuscules ou minuscules.

Quelques exemples :

Exemples PSR-0

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/ IsolatedClassLoader.php \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

Enfin, un exemple simple et rapide d'autoloader qui respecte PSR-0 : Exemple simple et rapide d'autoloader PSR-0

<?php function autoload($className) { $className = ltrim($className, '\\'); $fileName = ''; $namespace = ''; if ($lastNsPos = strripos($className, '\\')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; } require $fileName;

Un exemple plus concrt d'autoloader PSR-0 est celui de Composer. Composer est un systme de gestion de dpendances entre diffrents projets PHP complmentaires, un bon exemple d'utilisation d'un autoloader unique pour charger tout le monde.

-9Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/

Autochargement de classes en PHP par Julien Pauli (Tutoriels, articles et confrences PHP et developpement web) (Blog)

IV - Conclusions
L'auto-chargement de classes semble tre une problmatique simple, mais sur des projets de grosse taille, complexes, ou amens le devenir, la question de la gestion de l'autoload devient un casse-tte pourtant crucial. Il faut pouvoir voluer avec des autoloads "externes", personnaliss ou imports, s'occuper de la gestion des erreurs et pouvoir crer plusieurs autoloaders empils. Heureusement, il existe maintenant une norme, PSR-0, implmente quasi-totalement dans le framework Symfony2 ou encore dans le projet Doctrine2, et la plupart des projets webs professionnels l'utilise, mme s'ils n'utilisent pas Symfony2 ou Doctrine2. Documentation officielle de Zend_Loader_Autoloader Autoloader Symfony2 Introduction la SPL Documentation officielle sur autoload de la SPL

- 10 Copyright 2012 Julien Pauli. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://julien-pauli.developpez.com/tutoriels/php/autoload/