PHP SPL autoload vs. __autoload

Posted: 2010/11/03 in OOP, PHP

A very nice feature in PHP 5 is ‘autoloading’ which allows for (1) class files (usually .php or .php.inc or .inc) to be automatically loaded when needed and similarly (2) only those files that need to be included are included (a little bit of memory savings).

In the past, I have used the __autoload() function which tells PHP to run a function I have created every time a class is instantiated with new (or called statically).

Recently, however, I came across an SPL version of autoloading. The biggest benefits of using the SPL version (that I can see to-date) are:

  • more than one function can be used/registered — functions are chained together and used sequentially up to the point of one function loading the class file.
    + functions can be unregistered on-the-fly, too.
  • there is some nice error handling that can be implemented (see example 3), although some hat try/catch so this may not fit your coding style.
  • using a different extension (i.e. not .php or .php.inc or .inc) if you so choose with spl_autoload_extensions()
  • makes sure that ‘my’ autoloading class is not overwritten!  If __autoload() is run later, my spl_autoload_register()’ed functions will not be replaced.

I rather like using SPL functions and attempt to use it when I can, presuming (1) I’m using PHP 5+ and (2) I can figure out what the SPL is doing (ha!).

So I wrote a very simple autoloader that I can now include_once() and it will both create the autoloading function and register it.  Since I always seem to create a directory called ‘classes‘ that holds all classes (creative, eh!), I went ahead and hard-coded it into the function.  If I wanted to add some other functions that look in other directories (ex. /var/www/FavoriteZendLibraries), I can do that easily with the spl_autoload_register() function (i.e. create a function that looks there instead of in ‘./classes‘).
Also, I use the underscore-to-slash paradigm for naming classes so that class ‘model_db_login’ would be found in ‘./classes/model/db/login.php‘.

Here it is (if you want the code, you should see a little box in the upper right of the code-box when you hover over any part of the code – you can ‘copy to clipboard’ with the second icon from the left or use the first icon to view-source and then copy the source):

/*
 * This code is free software; you can use it, redistribute it, and/or modify as you wish.
 * This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY - implied or otherwise.
 * This code is distributed "as is."  All risk and cost are assumed by the user of the code and not the creator thereof.
 * If you want to give attribution to the original creator of the original code, his name is David Malouf and he is, probably, available at EmailTheDavid@gmail.com
 */

/**
 *
 *  Takes class_with_underscores (or not) and converts underscores to
 *    folder names.  Then attempts to include_once the class.  Returns TRUE
 *    on success, E_USER_WARNING and FALSE if it cannot load the class
 *
 *  Example: data_db_login  ==  ./classes/data/db/login.php
 *
 *  Usage:
 *    include ('./autoloader.php')    // or whatever you want to call this file
 *    spl_autoload_register('class_autoloader');
 *
 *
 * @param string $class Class name with underscores representing directories
 * @return bool Returns TRUE upon success, E_USER_WARNING and FALSE upon failure
 */

function class_autoloader($class) {
   // convert '_' to '/'
   $folderedClass = str_replace('_', '/', $class);

   // presumes classes are in './classes'
   $theClass = dirname(__FILE__) . '/classes/' . $folderedClass . '.php';

   if (file_exists($theClass) && include_once($theClass)) {
      return TRUE;
   } else {
      trigger_error("The class '$class' or the file '$theClass' failed to spl_autoload  ", E_USER_WARNING);
      return FALSE;
   }
}

Now, if I wanted to make sure I didn’t override someone else’s __autoload, I can add it to the spl_autoload stack quite easily with the spl_autoload_functions() function that passes back an array of the currently loaded functions like this:

.
// if __autoload is active, put it on the spl_autoload stack
if (is_array(spl_autoload_functions()) && in_array('__autoload', spl_autoload_functions())) {
   spl_autoload_register('__autoload');
}

// NOW go about adding my own autoloader above...
include ('./autoloader.php')    // or whatever you want to call this file
spl_autoload_register('class_autoloader');
.

edited 2013 Aug 26 to include “is_array(spl_autoload_functions())” check as this will throw errors if nothing has been loaded into the spl_autoload stack.

Advertisements
Comments
  1. ganaysa says:

    When using spl_autoload_register() with set_include_path, should I include its file in every page I want to instantiate a class?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s