SPL Autoloading best practices

3.9k views Asked by At

In my include_path on the server-side I have a reference to a pear directory, in '/usr/share/pear/'. Within my applications I include files from a common library, living in '/usr/share/pear/library/' with require_once 'library/file.php'.

I've recently started using the spl autoloader, I noticed in the loader function you have to determine the logic with which to include the file. My first way of doing this was trying to include a file and suppressing it with @ to see if it would fail, e.g. @include 'library/file.php' however I think mostly because I read a lot about @ being a bad practice I decided to manually do the work myself by exploding get_include_path by the PATH_SEPARATOR and seeing if the directory is what I want it to be, then doing a file_exists and including it.

Like so:

function classLoader( $class ) {
    $paths = explode( PATH_SEPARATOR, get_include_path() );
    $file = SITE_PATH . 'classes' . DS . $class . '.Class.php';
    if ( file_exists( $file) == false ) 
    {
        $exists = false;
        foreach ( $paths as $path ) 
        {
            $tmp = $path . DS . 'library' . DS . 'classes' . DS . $class . '.Class.php';
            if ( file_exists ( $tmp ) ) 
            {
            $exists = true;
            $file = $tmp;
            }
        }
        if ( !$exists ) { return false; }
    }
    include $file;
}

spl_autoload_register('classLoader');

Did I go the wrong route? Should I have just done the @include business or am I doing it somewhat in the right direction?

2

There are 2 answers

0
ringmaster On BEST ANSWER

One thing that the Habari project autoloader does that's interesting is cache the whole class file list in memory so that it's not doing disk searches for the files every time a class is requested.

Essentially, you declare a static inside your __autoload() that holds an array of all of the class files, indexed by the class that will cause them to load. For example, the code would use Dir or glob() to generate this static array:

$class_files = array(
  'user' => '/var/www/htdocs/system/classes/user.class.php',
);

Then you simply include $class_files[$class] to get the correct file. This is nice and speedy because it gets the catalog from the disk all at once, rather than generating the list or searching for a specific filename each time a new class is referenced. (You would be surprised how much of a speed difference it makes.)

If the class name isn't a key in the array, you can throw a custom exception or generate a stub/mock class to return. Also, if you check out the Habari system autoloader, you'll see that Habari implements __static() in classes that are autoloaded, which is like a constructor for static classes.

include_once() is to be avoided, and the @ operator is unnecessary if you've checked for the file to include.

1
johannes On

I personally go the way using

function autoload($class) {
    /* transform class name into filename ... */
    include $class;
}

even without the @ to ease debugging (errors are shut down/logged in production)

You might also be interested in the related discussion on the PHP developer list: http://marc.info/?t=125787162200003&r=1&w=2