PSR4是一种自动加载规范,老版本是PSR0,尽管thinkPHP支持PSR4和PSR0的自动加载方式,可是默认也是优先进行PSR4加载,若是失败,再进行PSR0的加载。本篇文章只会讨论PSR4的加载。php
代码示例:linux
spl_autoload_register(function ($class) { // 指定项目的命名空间前缀 $prefix = 'Foo\\Bar\\'; // 指定项目的根目录 $base_dir = __DIR__ . '/src/'; // 判断类的前缀是否是上面的命名空间前缀 $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // 不是,则交给其余类加载器去加载,不使用PSR4 return; } // 获取相对的命名空间 $relative_class = substr($class, $len); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php // 使用根目录替换命名空间前缀,使用目录分隔符替换相对类名中的命名空间分隔符,而后再加上.php $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // 若是该类存在,则require它 if (file_exists($file)) { require $file; } });
从上面的代码中,咱们就能够知道PSR4究竟是干什么的。
这个规范主要就是将类转换成物理路径。thinkphp
好比thinkphp典型的一个控制器:Index.phpwindows
<?php namespace app\index\controller; class Index{ }
那么在加载的时候,传给这个PSR4的时候,$class=app\index\controller\Index;
数组
假设当前的根目录为:E:\app
当前的命名空间前缀为:app
根据前面的转换步骤,这个类的路径应该是在:E:/app/index/controller/Index.php
app
路径的斜杆(/)跟反斜杆(\)。在windows中一般是使用反斜杆做为路径分隔符的,而在linux中,经过是使用斜杆做为路径分隔符的。不过windows如今的API都支持使用斜杆做为路径分隔符了,而若是使用反斜杆的话,那么在单引号中,还须要写成\才能当成\。而linux中是使用/,所以咱们的路径表示即是使用斜杆了。composer
有同窗跟我反映说,php单引号不是不会被转义吗?这个确实是,不过对于要输出单引号,所以在单引号字符串中,单引号是须要使用反斜杆转义才能输出的,而反斜杆自己也是须要使用反斜杆来转义,对于其余的转义,就真的不会了。框架
类库映射实际上就是保存一个键值对数组,键值为类名,值为物理路径,这样当类加载的时候,直接查找该数组就行。thinkphp5
而对于PSR4,咱们根据上面知道,须要注册根目录跟命名空间前缀。
在thinkphp中注册了五个命名空间前缀:ui
self::addNamespace([ 'think' => LIB_PATH . 'think' . DS, 'behavior' => LIB_PATH . 'behavior' . DS, 'traits' => LIB_PATH . 'traits' . DS, ]);
还有两个是能够配置的:
self::$namespace = $config['app_namespace']; Loader::addNamespace($config['app_namespace'], APP_PATH); if (!empty($config['root_namespace'])) { Loader::addNamespace($config['root_namespace']); }
所以在配置文件中的app_namespace就是指明应用的命名空间前缀。好比默认为app对应着跟目录为application。
当使用PSR4方式读取失败的话,那么还有备选的目录能够用来读取,thinkphp即是使用这种方式做为扩展目录的读取:
// 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) { return $file; } }
$logicalPathPsr4
就是这事将命名空间分隔符转换为目录分隔符再加上.php
而已。
不过,一般来讲,开源的扩展应该使用composer开发。而只有私人的扩展,通常才放在extend目录下的。
为何TP不彻底使用composer的加载器呢?
一是彻底基于composer的话,那么当composer更新的时候,框架也须要相对应地调整,所以不可以彻底地专一于框架的开发。二若是彻底抛弃composer而专一于框架,又像是捡了芝麻丢了西瓜。所以将composer做为框架的延伸扩展,无疑是一种比较好的折中方案。
原文连接:https://www.kancloud.cn/code7/tp5/343057