- Si la fonction
__autoload()
est appelée, c'est que la classe n'est pas définie, donc il est inutile de vérifier qu'elle n'existe pas à l'aide declass_exists()
. - Si la classe n'existe pas, c'est que le fichier la définissant n'a jamais été inclus, donc il n'y a aucun besoin de faire appel à
require_once()
, un simplerequire()
est suffisant.
Certain pourrait me retorquer que l'appel à class_exists()
a sa raison d'être si le développeur choisit d'utiliser directement __autoload()
pour charger une classe à la demande, d'une manière analogue à require_once()
ou require()
.
Je leur répondrai que je ne vois pas alors l'intérêt d'utiliser le mécanisme d'autoloading
si ce n'est pas pour s'en servir.
Ensuite, je vous ai induit en erreur, car il n'y a pas deux, mais bien trois paradoxes dans ce code.
Certain l'ont en parti détecté, mais sans aller jusqu'au bout de leur réflexion.
Ce troisième paradoxe est induit par l'utilisation du second paramètre passé à class_exists()
, en l'occurence false
.
Sans ce paramètre, class_exists()
utilise le mécanisme d'autoloading
pour tenter de charger la classe si elle n'existe pas.
Dans notre contexte, s'il n'avait pas été utilisé, il y aurait eu un réel risque de générer une boucle infinie dans le cas ou la classe que __autoload()
doit charger n'existe pas, ce qui est forcément le cas puisque nous sommes justement dans ce cas lorsque cette fonction est appelée par PHP.
En effet, __autoload()
aurait fait appel à class_exists()
qui aurait fait appel à __autoload()
qui aurait fait appel... vous connaissez la suite.
Le troisième paradoxe est donc qu'un ou plusieurs développeurs ont été suffisament intelligent pour utiliser correctement class_exists()
dans le cadre d'une fonction __autoload()
alors qu'ils faisaient dans le même temps quelque chose de complétement con inutile.
Enfin, certain ont relevé un problème relatif à l'utilisation de dirname()
.
De mon point de vue, c'est plus un problème lié à la performance du code qu'un réel paradoxe.
Voici donc une version fonctionnellement identique du code concerné, mais corrigée et optimisée :
function __autoload($className)
{
static $classesDirectory = null;
if ($classesDirectory === null)
{
$classesDirectory = realpath(dirname(__FILE__).'/../classes') . '/';
}
require($classesDirectory.$className.'.php');
}
8 réactions
1 De EnZ - 14/10/2009, 12:48
J'avais relevé qu'il manquait le realpath. YATA ! :D
J'étais pas au point pour le reste, j'avais l'idée mais mal analysé.
Bref.
Peace
2 De mageekguy - 14/10/2009, 12:58
@EnZ :
L'utilisation de realpath() est loin d'être absolument nécéssaire, bien au contraire, mais j'aime avoir un chemin absolu "véritable" dans mes messages d'erreur.
Je préfere donc sacrifier un peu de performance pour avoir le chemin du fichier à inclure résolu.
3 De jp.fox - 14/10/2009, 21:33
M'en suis pas si mal tiré non plus alors ^^
http://blog.mageekbox.net/?post/200...
4 De desfrenes - 14/04/2010, 09:15
Tu vas adorer :
5 De mageekguy - 14/04/2010, 09:23
@desfrenes : BWAHAAHAHAHHAAAAAAAA.
Merci pour cette éclat de rire matinal en cette triste matiné grise.
6 De desfrenes - 14/04/2010, 09:46
ça vient de swift mailer, librairie intéressante fonctionnellement parlant. Depuis quelques semaines c'est un projet qui a été repris par Fabien Potencier. J'imagine que cet autoloader n'est pas de son fait (il faudrait comparer avec celui de symfony).
7 De metagoto - 14/04/2010, 11:24
Le code de @desfrenes ne me choque pas trop. C'est le check du strpos() qui vous fait marrer ? (le reste est perfectible effectivement)
8 De desfrenes - 14/04/2010, 16:02
cf billet ci-dessus