我有一个小应用程序,我需要一个自动加载器。我可以很容易地使用symfony2类加载器,但它似乎有点矫枉过正。
那里有一个稳定极轻的psr-0自动加载器吗?
答案 0 :(得分:28)
你要求非常轻量级,让我们这样做;)
Timothy Boronczyk写了一篇不错的最小SPL自动加载器:http://zaemis.blogspot.fr/2012/05/writing-minimal-psr-0-autoloader.html
我压缩了这样的代码:
function autoload1( $class ) {
preg_match('/^(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) );
require str_replace( '\\', '/', $match[ 1 ] )
. str_replace( [ '\\', '_' ], '/', $match[ 2 ] )
. '.php';
}
然后将此[autoload3]与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是最短的!
让我们使用稳定的&极轻量级(175b!)自动加载器文件:
<?php spl_autoload_register(function ($c){preg_match('/^(.+)?([^\\\\]+)$/U',ltrim($c,'\\'),$m);require str_replace('\\','/',$m[1]).str_replace(['\\','_'],'/',$m[2]).'.php';});
也许我疯了,但你问极端,不是吗?
编辑:感谢Alix Axel,我缩短了代码(只有100b!)并使用了include而不是require,以防你有各种自动加载策略用于旧库(然后是各种自动加载器) spl autoload stack ...)。
<?php spl_autoload_register(function($c){@include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';});
如果您想让它更短/更好,请使用此gist。
答案 1 :(得分:15)
PSR-0 specification document有一个示例兼容的自动加载器功能,它已经很短了:
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;
}
它的使用非常简单:
spl_autoload_register('autoload');
缺点是,您需要使用include_path
指令配置它所使用的基目录。为了支持混合PSR-0自动加载器倾向于SPL语义,以下一个支持包括路径和spl自动加载扩展:
$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 Symfony2 ClassLoader Component有利于在此处进行更多配置。您可以通过Pear或Composer轻松安装它(symfony/class-loader on Packagist)。它是它自己的一个组件,被很多人使用,并且经过了相当好的测试和支持。
答案 2 :(得分:10)
SplClassLoader似乎是一个正确的选择。它本身就是一个实现proposed by PSR-0。
答案 3 :(得分:4)
完全相当于the answer @hakre provided,只是更短:
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');
}
您也可以通过将$path = null;
更改为其他值来设置基目录,或者只是这样做:
$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);
}
}
答案 4 :(得分:1)
doctrine classloader是另一个不错的选择。您可以使用composer
轻松安装它答案 5 :(得分:0)
这不是问题的直接答案,但我发现上述答案在独立的PHP脚本上运行良好,但在某些框架中使用时会引起问题,例如Joomla。
对于使用Joomla的任何人来说,事实证明框架中已经内置了一个兼容的自动加载器,因此您不需要使用上述功能。在那个例子中,只需调用JLoader :: registerNamespace()....例如:
JLoader::registerNamespace('Solarium', JPATH_LIBRARIES . DS . 'solarium-3.2.0' . DS . 'library');
答案 6 :(得分:0)
function autoload($fullClassName) {
$name_elems = explode('\\', $fullClassName);
require __DIR__.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $name_elems).'.php';
}
这甚至支持以下内容: $ transformerContstraint = new \ Recurr \ Transformer \ Constraint \ AfterConstraint(new DateTime());
把它放在/vendor/Recurr/Transformer/Constraint/AfterConstraint.php