Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - most lightweight psr-0 compliant autoloader

I have a tiny application that i need an autoloader for. I could easily use the symfony2 class loader but it seems like overkill.

Is there a stable extremely lightweight psr-0 autloader out there?

like image 528
Marty Wallace Avatar asked Aug 22 '12 22:08

Marty Wallace


People also ask

What PSR-0?

PSR-0, also known as the Autoloading Standard, prescribes that classes and namespaces in PHP should match the directory and file structure, and vice-versa. PSR-4 allows specifying a namespace prefix for a given directory explicitly.

What is PSR autoloading?

Overview. This PSR describes a specification for autoloading classes from file paths. It is fully interoperable, and can be used in addition to any other autoloading specification, including PSR-0. This PSR also describes where to place files that will be autoloaded according to the specification.

Which autoloader should I use?

You can use any one of the PSR-0 compliant autoloaders from frameworks such as Symfony, Pear2, AuraPHP (which is for PHP 5.4+), etc. and adhere to the rules above with your own code to take advantage of autoloading without the uncertainties I discussed previously.

What is the best way to autoload in PHP 5?

I recommend you use one of the PSR-0 standard autoloaders instead. PHP 5 introduced the magic function __autoload () which is automatically called when your code references a class or interface that hasn’t been loaded yet. This provides the runtime one last chance to load the definition before PHP fails with an error.

What are the disadvantages of the __autoload() function in PHP?

The major drawback to the __autoload () function is that you can only provide one autoloader with it. PHP 5.1.2 introduced spl_autoload () which allows you to register multiple autoloader functions, and in the future the __autoload () function will be deprecated.

What is SPL_autoload_register() used for?

The introduction of spl_autoload_register () gave programmers the ability to create an autoload chain, a series of functions that can be called to try and load a class or interface. For example:


2 Answers

You ask extremely lightweight, let's do so ;)

Timothy Boronczyk wrote a nice minimal SPL autoloader : http://zaemis.blogspot.fr/2012/05/writing-minimal-psr-0-autoloader.html

I condensed the code like this:

function autoload1( $class ) {
    preg_match('/^(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) );
    require str_replace( '\\', '/', $match[ 1 ] )
        . str_replace( [ '\\', '_' ], '/', $match[ 2 ] )
        . '.php';
}

Then compare (minified versions of) this [autoload3] with short @Alix Axel code [autoload4] :

function autoload3($c){preg_match('/^(.+)?([^\\\\]+)$/U',ltrim($c,'\\'),$m);require str_replace('\\','/',$m[1]).str_replace(['\\','_'],'/',$m[2]).'.php';}
function autoload4($c){require (($n=strrpos($c=ltrim($c,'\\'),'\\'))!==false?str_replace('\\','/',substr($c,0,++$n)):null).str_replace('_','/',substr($c,$n)).'.php';}

autoload3 is the shortest !

Let's use stable & extremely lightweight (175b !) autoloader file :

<?php spl_autoload_register(function ($c){preg_match('/^(.+)?([^\\\\]+)$/U',ltrim($c,'\\'),$m);require str_replace('\\','/',$m[1]).str_replace(['\\','_'],'/',$m[2]).'.php';});

Maybe i'm crazy but you Asked for extreme, no?

EDIT: Thanks to Alix Axel, i've shorten the code (only 100b !) and used include instead of require in case you have various autoloading strategy for old libs (and then various autoloader in spl autoload stack...).

<?php spl_autoload_register(function($c){@include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';});

If you want to make it shorter / better, please use this gist.

like image 109
Adrien Gibrat Avatar answered Sep 18 '22 08:09

Adrien Gibrat


The PSR-0 specification document has an examplary compatible autoloader function that is already pretty short:

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strripos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}

It's usage is pretty straight forward:

spl_autoload_register('autoload');

The shortcoming with it is, that you need to configure base-directories it works on with the include_path directive. To support a hybrid PSR-0 autoloaders leaned onto SPL semantics, the following one supportss include path and spl autoload extensions:

$spl_autoload_register_psr0 = function ($extensions = null) 
{
    $callback = function ($className, $extensions = null) 
    {
        if (!preg_match('~^[a-z0-9\\_]{2,}$~i', $className)) {
            return;
        }
        null !== $extensions || $extensions = spl_autoload_extensions();
        $extensions = array_map('trim', explode(',', $extensions));
        $dirs = array_map('realpath', explode(PATH_SEPARATOR, get_include_path()));

        $classStub = strtr($className, array('_' => '/', '\\' => '/'));

        foreach ($dirs as $dir) {
            foreach ($extensions as $extension) {
                $file = sprintf('%s/%s%s', $dir, $classStub, $extension);
                if (!is_readable($file)) {
                    continue;
                }
                include $file;
                return;
            }
        }
    };

    return spl_autoload_register($callback);
};

The The Symfony2 ClassLoader Component has the benefit to allow more configuration here. You can install it easily via Pear or Composer (symfony/class-loader on Packagist). It is a component on it's own that is used by many and fairly well tested and supported.

like image 24
hakre Avatar answered Sep 19 '22 08:09

hakre