У меня есть крошечное приложение, для которого мне нужен автозагрузчик. Я мог бы легко использовать загрузчик классов symfony2, но он кажется излишним.
Есть ли стабильный чрезвычайно легкий psr-0 автонагрузчик там?
У меня есть крошечное приложение, для которого мне нужен автозагрузчик. Я мог бы легко использовать загрузчик классов symfony2, но он кажется излишним.
Есть ли стабильный чрезвычайно легкий psr-0 автонагрузчик там?
Вы задаете очень легкий вес, пусть это делает;)
Тимоти Борончик написал хороший минимальный автозагрузчик 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';});
Может быть, я сумасшедший, но вы спросили о крайности, нет?
EDIT: Благодаря Alix Axel, я сократил код (только 100b!) и использовал include, вместо того, чтобы требовать, чтобы у вас была разная стратегия автозагрузки для старых библиотек (а затем различные автозагрузчики в spl autoload stack...).
<?php spl_autoload_register(function($c){@include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';});
Если вы хотите сделать это короче/лучше, используйте gist.
В документе спецификации PSR-0 есть примерная совместимая функция автозагрузчика, которая уже довольно короткая:
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_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);
};
Компонент Symfony2 ClassLoader имеет преимущество, позволяющее больше конфигурации здесь. Вы можете легко установить его через Pear или Composer (symfony/class-loader в Packagist). Это компонент, который используется многими и достаточно хорошо протестирован и поддерживается.
SplClassLoader кажется правильным выбором. Это реализация предложенная самой PSR-0.
Точный эквивалент ответа @hakre предоставлен, короче:
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);
}
}
doctrain classloader - еще один хороший выбор. Вы можете легко установить его с помощью composer
Это не прямой ответ на вопрос, но я обнаружил, что вышеупомянутые ответы отлично работали на автономных скриптах PHP, но вызывали проблемы при использовании в определенных рамках, таких как Joomla.
Для всех, кто использует Joomla, оказывается, что в инфраструктуру уже встроен совместимый автозагрузчик, поэтому вам не нужно использовать вышеуказанные функции. В этом случае просто вызовите JLoader:: registerNamespace().... например:
JLoader::registerNamespace('Solarium', JPATH_LIBRARIES . DS . 'solarium-3.2.0' . DS . 'library');
function autoload($fullClassName) {
$name_elems = explode('\\', $fullClassName);
require __DIR__.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $name_elems).'.php';
}
Это даже поддерживает такие вещи, как: $ transformerContstraint = new\Recurr\Transformer\Constraint\AfterConstraint (новый DateTime());
Просто поместите его в/vendor/Recurr/Transformer/Constraint/AfterConstraint.php