Composer与自动加载
PSR-4
这个 PSR 描述的是通过文件路径 自动载入 类的指南;它作为对 PSR-0 的补充;根据这个 指导如何规范存放文件来自动载入;
术语「类」是一个泛称;它包含类,接口,traits 以及其他类似的结构;
完全限定类名应该类似如下范例:
()*
完全限定类名必须有一个顶级命名空间(Vendor Name);
完全限定类名可以有多个子命名空间;
完全限定类名应该有一个终止类名;
下划线在完全限定类名中是没有特殊含义的;
字母在完全限定类名中可以是任何大小写的组合;
所有类名必须以大小写敏感的方式引用;
当从完全限定类名载入文件时:
在完全限定类名中,连续的一个或几个子命名空间构成的命名空间前缀(不包括顶级命名空间的分隔符),至少对应着至少一个基础目录。
在「命名空间前缀」后的连续子命名空间名称对应一个「基础目录」下的子目录,其中的命名 空间分隔符表示目录分隔符。子目录名称必须和子命名空间名大小写匹配;
终止类名对应一个以 .php 结尾的文件。文件名必须和终止类名大小写匹配;
自动载入器的实现不可抛出任何异常,不可引发任何等级的错误;也不应返回值;
自动加载是用到了 spl_autoload_register函数,spl_autoload_register(array(class,load));load自定义函数,class为定义load的类,load是自定义函数,函数中写了通过class寻找目标文件与引入。
Composer的自动加载
使用自动加载时,先通过名称空间的前缀,找到对应的映射路径,在根据PSR0规范找到对应的类定义文件。但是这里有些例外,类名中的下划线在PSR4中是不需要转换成目录的。
composer中的自动加载,通过composer.json生成autoload_psr4.php,autoload_psr0.phpautoload_classmap等文件,这些文件保存这命名空间与目标文件的映射目录
在引入vender/autoload.php,通过 ComposerAutoloaderInit获取load对象,
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit5b6df0852e175d157f350339232d00ce', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();//获取loader对象
spl_autoload_unregister(array('ComposerAutoloaderInit5b6df0852e175d157f350339232d00ce', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit5b6df0852e175d157f350339232d00ce::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';###此处加载psr4标准的文件
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);###将psr4的命名空间与目标路径的规则
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);##通过loader与resiter完成注册
return $loader;
}
#### 'Library\\sso\\' => array($baseDir . '/Library/sso'), psr4的命名空间与路径的映射关系
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;//###设置 loader命名空间的长度 这个是方便检索,快速查找命名空间是否注册在psr4中
$this->prefixDirsPsr4[$prefix] = (array) $paths; //规则设置到的 loader的psr4的注册表中
}
}
当在项目中遇到为引入的的类,则会触发classloader中的loadClass函数 ,函数通过classloader的注册数组寻找类的所在目录并引人文件。