Some tricks with Autoloaders

Autoloaders are a great feature of PHP5. Used properly they can help to really ‘clean up’ your code, negating the need for include or require statements. They can also lead to a real increase in performance as class files are only loaded and parsed when needed (lazy loading) instead of at the beginning of every request. I was recently working on some code where I wanted to serialise some objects, store them in the session and unserialise them on the next page request. The problem with this is that when you unserialise an object if the class defining the object has not already been loaded you end up with an instance of PHP_incomplete_class. While rooting around looking for a way to handle this with autoloaders I discovered some interesting things about them. There’s nothing new here but I thought I would draw all of these tips together into one blog post.

Autoloading classes after calling unserialize()

There’s an setting in php.ini that allows the user to specify a callback function to call after an object or other data structure has been unserialised. If you set this callback to be your autoloader class files will be automatically loaded when you unserialise an object. This setting can be defined in php.ini, in an .htaccess file or in your code using ini_set() such as:


function __autoload($classname){

//Code to autoload a class here.

}

ini_set('unserialize_callback_func', '__autoload');

This is nice and simple but does require an extra function call in your code and is something you have to remember in each project. Luckily, there is another way.

Using spl_autoload_register()

The function spl_autoload_register() can be used to register a stack of user defined autoloaders. Each autoload function is then called in turn until the class is loaded. If no class can be found PHP dies with a fatal error. This obviously has benefits if your project needs to implement different logic to load different classes. You can encapsulate the different code to load classes in different functions and register each as an autoloader. Using spl_autoload_register() also has several other benefits, one of which is that that the autoload stack created is automatically added as a callback when unserialising an object. This means that it’s not necessary to call ini_set to set up the callback function. Code to do this could look something like this:


function autoload($classname) { //Notice the lack of underscores in the classname.

//Code to load the class

}

spl_autoload_register('autoload');
//Multiple calls to spl_autoload_register() will add other autoload functions

After running the code above it is no longer necessary to call ini_set() to set our autoloader function as an unserialise callback. Using spl_autoload_register() can have some other benefits though.

Using PHP’s default autoloader

The first parameter to spl_autoload_register(), the name of the autoload function, is optional. The PHP manual says ‘If no parameter is provided, then the default implementation of spl_autoload() will be registered’. What this means is that if you call spl_autoload_register() without specifying a name of one or more autoload functions a default autoloader, written in C and which is part of the core PHP engine, is set as the autoloader. This will take the class name requested, lowercase it (note this!), and look for a file that contains the name of the class in every directory in the include path. For example, if your class name was Foo_Bar the default autoloader would look for a file name ‘foo_bar.php’ in every directory in the include path. Because this function is written in C it should be a little faster than any autoload function you define in PHP. You can also use the function spl_autoload_extensions() to define the file extensions that will be looked for to autoload classes. This function takes a comma separated string of the different file extensions that you want to use, such as ‘spl_autoload_extensions(“.class.php,.php,.inc”)’.

Using these tricks it’s possible to define a very efficient autoloading scheme using very little code, providing you have one class per file and that the filename is the lowercased name of the class. You simply need to add the directories holding your classes to the include path, register the extensions your class files use and call spl_autoload_register. This could look something like the following:

//Define the paths to the directories holding class files
$paths = array(
'path/to/class/files/',
'another/path/to/class/files'
);
//Add the paths to the class directories to the include path.
set_include_path(get_include_path() . PATH_SEPARATOR . implode(PATH_SEPARATOR, $paths));
//Add the file extensions to the SPL.
spl_autoload_extensions(".class.php,.php,.inc");
//Register the default autoloader implementation in the php engine.
spl_autoload_register();

That’s really all there is to it.

If your code is namespaced and your directory structure mirrors the namespace things are even simpler. Assuming all of your classes are in the same top level directory all you need to do is to add that directory to the include path. The default spl_autoload function will convert the namespace path into a directory path to load the class. For example, if you defined a class named ‘Baz’ in the namespace ‘myapp\Foo\Bar’ spl_autoload will look for ‘myapp/Foo/Bar/baz.php’.

As I said before there’s nothing really new in this post but hopefully someone will find having this information aggregated together useful.

4 thoughts on “Some tricks with Autoloaders

    1. Sure. I assume you mean using the default autoloader defined by the SPL? If so then as long as your namespaces map out to the directory structure you should be good to go. Assuming you had a class with a fully qualified name of Foo\Bar\Baz the default autoloader would look in file foo/bar/baz.php to load the class. For this to work you would need to make sure that the directory holding all of your directory/namespaces was in the include path.

      HTH.

  1. Hi @jeremy:
    You are saying after defining namespace spl_autoload find file on same hierarchy as namespace defined, like:
    namespace app\mod\classname
    PHP: $cls = new \app\mod\classname;

    as i understand to read your blog, in above case class must be stored in app folder > mod folder > class file, namespaces just help code to process fast as possible or by namespace can we play dynamically?

    1. Hi Farhan,

      Thanks for the comment. If I’m reading it correctly you’re asking if it’s necessary for namespaces to live in their own folders in the file system. There is no law saying that this has to be the way and you can be as creative as you like with your class loading in autoloaders. That said, it has become an (un)official standard to have one directory per namespace level (all major frameworks and libraries do it this way). Have a look at http://phpmaster.com/autoloading-and-the-psr-0-standard/ for more information on the PSR-0 standard and autoloaders. One other advantage of this is that if you use Composer for dependency management it can generate your autoloaders for you.

      I hope that answers your question.

      Best wishes,

      Jeremy.

Leave a Reply