Skip to Content Skip to Search Go to Top Navigation Go to Side Menu
Search on Site

ClassLoader

Monday, October 30, 2006

I have a sort of love hate relationship with OO support in PHP. On one hand it looks like a dirty hack due to a combination of the duck typing, lack of function overloading, no proper namespaces and the way everyone talks about object methods when the code itself calls them functions. On the other hand it just feels right (although I’m told this kind of wooly thinking is my degree showing) and if you are putting anything together where scripts run to more than a hundred lines or so it’s really the only way to do it and keep it all manageable. One of the major problems I have with the whole thing is that there is no standardised way to store your class definitions and consequently no way to import them in a neat and tidy way. I personally favour having each class and interface in it’s own file, named thus:

DatabaseConnection.class.php
SQLQuery.class.php
JSONableItem.interface.php
etc..

This way you can identify what is in each file just by reading the name and you can order them in directories like so:

ajax
JSONableItem.interface.php
database
DatabaseConnection.class.php
SQLQuery.class.php
etc..

Even giving you a sort of memetic namespace of

ajax.JSONableItem
database.DatabaseConnection
database.SQLQuery
etc..

Which encourages code re-use by making it very easy to transfer classes between projects. This brings me on to the next problem in that there is no standardised way of importing these classes into your script files. I normally have one file that imports all the class definitions into the project, somewhere high up on the bootstrap page but this means that every single class in the project is being loaded for each request to the server that is answered by PHP - not exactly ideal. I found a little class on the Pure PHP website called Include_once which is based on an interesting little idea - keep a list of imported files and only import a requested file if it is not in the list. Inspired by this I’ve written a little utility class rather unimaginatively named ClassLoader which does the above but via a sort of namespace that allows for nice structuring of class definition files in the file system and also the importing of whole folders of class files (packages). An example of it’s use is as follows:

  1. ClassLoader::import(‘database.DatabaseConnection’);
  2. ClassLoader::import(‘database.SQLQuery’);

or even

  1. ClassLoader::import(‘database.*’);

There are also a couple of other fun methods

  1. ClassLoader::getClassesLoaded()

tells you how many classes have been loaded and

  1. ClassLoader::getLoadAttempts()

tells you how many times ClassLoader has been asked to load class definition files. The reason that these may be different is because you can use ClassLoader to include class definition files at the top of other class definition files much in the same way you’d use the import statement in Java. So for a trite example, with the following file structure:

classes
  pretend
    InterfaceA.interface.php
    ClassA.abstract.php
    ClassB.class.php
    ClassC.class.php
  util
    ClassLoader.class.php
index.php

InterfaceA.interface.php

  1. interface InterfaceA {
  2. public function someMethod();
  3. }

ClassA.abstract.php

  1. ClassLoader::import(‘pretend.InterfaceA’);
  2.  
  3. abstract class ClassA implements InterfaceA {
  4.  
  5. }

ClassB.class.php

  1. ClassLoader::import(‘pretend.ClassA’);
  2.  
  3. class ClassB extends ClassA {
  4.   public function someMethod() {
  5.  
  6.   }
  7. }

ClassC.class.php

  1. ClassLoader::import(‘pretend.ClassB’);
  2.  
  3. class ClassC extends ClassB {
  4.  
  5. }

index.php

  1. require(‘classes/util/ClassLoader.class.php’);
  2.  
  3. ClassLoader::import(‘pretend.ClassC’);
  4.  
  5. $foo = new ClassC();

Neat. Of course, you don’t have to follow my file naming convention, feel free to do whatever you want, as long as the file has the name of the contained class before the first ‘.’ and the last four characters are ‘.php’ Configuration of the class is pretty simple - just change the static member variable ClassLoader::$classPath to suit your set up. Just make sure it’s readable by PHP. So, for example:

  1. require(‘classes/util/ClassLoader.class.php’);
  2. ClassLoader::$classPath = $_SERVER[‘DOCUMENT_ROOT’] . ‘/includes/myclasses/’;

or

  1. require(‘classes/util/ClassLoader.class.php’);
  2. ClassLoader::$classPath = ‘/usr/local/share/php5/myclasses/’;

or similar. Given the above, there’s a really tiny part of me that says I should start using proper stuff like J2EE or something. I try not to listen to it.

Popularity: 38% [?]

Leave a Reply


In order to submit a comment, you need to mention your name and your email address (which won't be published).

Comment Form