PHP Autoloading

Like C, PHP initially started out as a “every file defines functions and variables and classes” language where using an entity assumed that it had already been defined (which, in practice, meant that the file it was defined in had already been included).

This led to several issues :

  • It was hard to find out what file contained what function. It was certainly possible to namespace functions based on the file name, but it required more effort than the amateur team workforce was capable of, and it made function names so much longer.
  • It was easy to mess things up when doing dynamic loading, because one could mistakenly load a dangerous or private file.
  • When serializing classes, one would have to determine where the class was defined when reloading the serialized data, so that the class definition could be loaded again.
  • Every time a class or function was used, the developer would have to check that the corresponding definition file was loaded as well. This led to loading many files that were not necessary just in case they would be used. Since PHP is not compiled, this meant parsing the files and populating the global scope with unnecessary entities.

Which is why autoloading was introduced.

The mechanism behind autoloading is simple : if at any point during the execution of a program the script uses a class that is not defined, the __autoload function is called with the name of that class as an argument. That function is then allowed to load a file or evaluate a script string in order to define that class.

The function obviously determines, using the class name, what source file defines that class, and loads it just in time for the class to be used. This solves all of the above issues in one strike:

  • There’s usually a clean convention for mapping class names to files. For instance, the Zend convention is that class Foo_Bar_Qux is defined in Foo/Bar/Qux.php within the include path. And if you don’t follow the convention, the code doesn’t work (of course, there’s still the issue of writing the code on Windows and then running into Linux case sensitivity).
  • Using Zend_Loader (or writing your own sane __autoload function) you can restrict dynamic loading to a single directory.
  • __autoload also triggers while deserializing.
  • Developers don’t need to include anything : every used class is included, and no class is included unless it’s used.

There is of course a slight performance penalty as the loader has to process the class name to find out what file to load, but bytecode caches work around this issue quite well when performance is important.

4 Responses to “PHP Autoloading”


  1. phifeshaheed - July 26, 2009 at 7:45 pm - Reply

    Bonjour,

    je dois réoudre un probleme sur une application que je dois coder sous zend framework, une application en apparence il s’agit essentiellement de faire de la saisie de données afin de générer des statistiques. Et donc pour cela on a différentes tables qui sont reliées en général à un formulaire qui va récolter les informations nécessaire pour les insérer dans cette table.

    Le petit piège sur ce projet c’est que les utilisateurs finaux souhaitent pouvoir ajouter des champs dans les différents formulaires si ils ressentent le besoin de récolter nouveaux types d’informations. Exemple tout bete: on récolte les informations sur les employés de l’entreprise à travers un formulaire qui comporte un champ téléphone fixe et il s’avert qu’on veuille ajouter un champ téléphone mobile. Jusque là so far so good, cependant afin de sauvegarder cette nouvelle info en base de données, typiquement on va devoir ajouter une nouvelle colonne dans la table Employée de notre base…

    L’application étant développée avec zend framework, c’ets donc là que se pose la tuile car on vient de modifier le modèle de données et donc il faut régénérer le modèle via doctrine ou propel ou la main sous zendDB. Il n’est évidemment pas question de livrer au client une appli sur laquelle il va devoir faire des lignes de commande pour générer des classes du modèle de données.

    ma question: Comment structurer ma base de données pour que je puisse faire les modifications attendues par mon client sans passer passer par l’ajout d’une nouvelle colonne et donc une modification du modèle de données nécessitant une régénération des classes du model?

    Exemple de tables: Produits (prix, description, nom), Magasins(adresse, type)
    exemples formulaire: saisie info produits, saisie info magasin
    Exemple modification: on veut pouvoir saisir et enregistrer en base le nom du fabriquant du produit, et l’on voudrai pouvoir saisir et enregistrer en base le nom du gérant du magasin. Comment pourrai t on structuré la base de donnée pour qu’elle puisse sous zend framework permettre ce type d’opération: ajout de champ formulaire et possibilité d’enregistrer les nouvelles saisies sans modifier la structure de la BDD?

    • ZF, comme n’importe quel framework, est un outil qui te permet d’accomplir plus rapidement certaines tâches pour lesquelles il a été conçu. Au vu de ta situation, qui ne correspond pas au champ d’action immédiat de ZF (modèle de données dynamique), il ne me semble pas clairement tranché que “adapter la situation à ZF” soit la bonne marche à suivre, et pas “résoudre le problème sans ZF”. En plus, comme ZF est constitué de bouts raisonnablement indépendants, ça ne te coûte rien de faire une partie isolée du produit sans ZF, et utiliser ZF partout ailleurs.

      La tâche qui consiste à enregistrer des données variées, et à modifier le modèle de données pendant le cycle de vie de l’application, est un problème qui est déjà résolu par les bases de données. Elles servent à ça. Vouloir “restructurer la base” pour pouvoir accomplir ce qu’elle sait déjà faire, mais dans le cadre de ZF, me semble une bonne recette pour 1° résoudre le problème moins bien que la base ne le fait déjà et 2° sortir assez du cadre de ZF pour n’en tirer aucun avantage.

      En bref: puisque tu devras de toutes façons écrire du code pour gérer le côté “dynamique” de ton modèle, pourquoi tiens-tu à utiliser ZF pour ce problème précis? Ne penses-tu pas que tu devras écrire moins de code si tu contournes ZF ici?

    • Bon, pendant qu’on y est, tu peux quand même aller regarder du côté d’une solution qui a (à mon avis) mal résolu ce problème : Magento stocke ses produits dans un système d’entité-attribut-valeur. Tu as en gros une table entité (entity_id + champs fixes), une table attribut (attribute_id, attribute_type, attribute_label) et pour chaque type d’attrbut (texte, entier, flottant, date…) une table valeurs (entity_id, attribute_id, value). Ajouter une colonne se traduit par l’ajout d’un nouvel attribut.

      Inutile de te dire que Magento est connu pour sa lenteur en ce qui concerne le traitement des produits, principalement à cause de la difficulté de manipuler proprement tout ce bazar. Heureusement, ils ont un système de cache qui permet d’accélérer grandement la lecture des données, mais je m’arrache régulièrement les cheveux quand il s’agit d’accéder à la base en écriture.

  1. 1 Autoloading : be friendly to intruders at Nicollet.Net

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>



1150 feed subscribers
(readers who polled a feed this week)