PHP - most lightweight psr-0 compliant autoloader

2019-01-08 20:25发布

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?

7条回答
Ridiculous、
2楼-- · 2019-01-08 21:05

The doctrine classloader is another good choice. You can easily install it with composer

查看更多
Melony?
3楼-- · 2019-01-08 21:14

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.

查看更多
Root(大扎)
4楼-- · 2019-01-08 21:16

An exact equivalent of the answer @hakre provided, just shorter:

function autoload($class) {
  $path = null;

  if (($namespace = strrpos($class = ltrim($class, '\\'), '\\')) !== false) {
    $path .= strtr(substr($class, 0, ++$namespace), '\\', '/');
  }

  require($path . strtr(substr($class, $namespace), '_', '/') . '.php');
}

You can also set the base directory by changing $path = null; to another value, or just do like this:

$paths = array
(
    __DIR__ . '/vendor/',
    __DIR__ . '/vendor/phunction/phunction.php',
);

foreach ($paths as $path)
{
    if (is_dir($path) === true)
    {
        spl_autoload_register(function ($class) use ($path)
        {
            if (($namespace = strrpos($class = ltrim($class, '\\'), '\\')) !== false)
            {
                $path .= strtr(substr($class, 0, ++$namespace), '\\', '/');
            }

            require($path . strtr(substr($class, $namespace), '_', '/') . '.php');
        });
    }

    else if (is_file($path) === true)
    {
        require($path);
    }
}
查看更多
唯我独甜
5楼-- · 2019-01-08 21:19

This is not a direct answer to the question, but I found that the above answers worked great on standalone PHP scripts, but were causing issues when used in certain frameworks, such as Joomla.

For anyone using Joomla, it turns out that there is a compatible autoloader already built into the framework, therefore you won't need to use the above functions. In that instance, just call JLoader::registerNamespace().... for example:

JLoader::registerNamespace('Solarium', JPATH_LIBRARIES . DS . 'solarium-3.2.0' . DS . 'library');
查看更多
霸刀☆藐视天下
6楼-- · 2019-01-08 21:22
function autoload($fullClassName) {
    $name_elems = explode('\\', $fullClassName);
    require __DIR__.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $name_elems).'.php';
}

This even supports things like: $transformerContstraint = new \Recurr\Transformer\Constraint\AfterConstraint(new DateTime());

Just put it in /vendor/Recurr/Transformer/Constraint/AfterConstraint.php

查看更多
▲ chillily
7楼-- · 2019-01-08 21:25

SplClassLoader seems like a right choice. It's an implementation proposed by PSR-0 itself.

查看更多
登录 后发表回答