So to use a class in PHP, usually, we first have to include the file that contains the definition for that class.

require('myclass.php');

$class = new MyClass;

But after you start instantiating a few classes here and there, problems arise.

  • If you call a lot of classes, the number calls to require() becomes big.
  • When you start including files in other files, you are not sure whether or not you’ve already included a certain file, so you use require_once(), which is inefficient.
  • Worst of all, included files become disorganized, and you may accidentally remove a require() that is needed, not in the current file, but in a file downstream, leading to a Fatal Error (if you use require() and not include()).

The solution: __autoload() The PHP autoload feature is one of the coolest features in the whole language. Basically, if PHP tries to load a class and cannot find the class definition, it will call the __autoload() function that you provide giving it the name of the class it can’t find. At that point, you’re on your own. But how to find the file located on disk? There are four strategies for finding the right class file.

  1. Keep all class files in one directory. Not a very attractive method.
  2. Maintain a global array of class names to class definition files. In this case, the name of the class is the key, and the location of the file on disk is the value. This global hash could be created in memory upon server start time, or created as the application executes. Obviously, seems kind of a heavy solution to me.
  3. Use a special container class that all other classes inherit from. This method is suitable mostly when attempting to unserialize objects (when unserializing objects, PHP must have the class definition to recover the object). This special container will automatically know the class file for the contained object. Then, the only class file that needs to be located is the container’s class file. (Autoloading in the context of object un/serialization is a special case of class loading.)
  4. Use a naming convention. The idea here is to name your classes in a way that corresponds to your file system. For example, Zend names their classes where underscores represent directories in the project. So the Zend_Auth_Storage_Session class is defined in the file Zend/Auth/Storage/Session.php. Autoload simply needs to replace the underscores for the system directory separator char and give it to require().

At work, we use #4, naming conventions. Why? Well, why not? The other methods are heavier or more complicated, and I don’t see any gain. By using a simple naming convention, never again will we need to call require() or include() in our app. As a bonus side-effect, the code is organized in a consistent matter. Provided we follow the naming convention that Zend (and PEAR) use, our __autoload() function looks like:

// by using PEAR-type naming conventions, autoload will always know where to
// find class definitions
function __autoload($class)
{
   require(str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php');
}