关于php规范psr4与psr0命名空间的理解
2017-07-19 11:38
701 查看
这几天在看php自动加载相关知识,这里记录一下。
use 命名空间只是防止命名空间的冲突,使用时仍需引入,这一步由自动加载来做。
与psr0不同,psr4不再转换 '_' 为文件分隔符,且 psr4有前缀gainia
以tp5的自动加载为例 Loader.php -> autoload() -> findFile()
可以看到psr0和psr4处理方式很类似,主要区别在于:
psr4 在拼接文件路径时会剔除掉前缀,而 psr0不会剔除。
psr0 会将类名中的 '_' 替换成 文件分隔符。
可以看个psr4例子:
![](https://img-blog.csdn.net/20160729175245815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
以第一个为例, 传入findFile()的$class 为 \Acme\Log\Write\File_Writer , 执行$dir . DS . substr($logicalPathPsr4, $length) 时剔除掉前缀 Acme\Log\Writer , 此时 $dir 为 ./acme-log-writer/lig/ ,拼接结果为 ./acme-log-writer/lib/File_Writer.php
如果是psr0 , 不剔除前缀,且替换下划线为文件分隔符,执行 $dir . DS . $logicalPathPsr0 结果为 ./acme-log-writer/lib/File/Writer.php。
这些差异也导致 psr4的文件路径看起来比较简洁。
use 命名空间只是防止命名空间的冲突,使用时仍需引入,这一步由自动加载来做。
与psr0不同,psr4不再转换 '_' 为文件分隔符,且 psr4有前缀gainia
以tp5的自动加载为例 Loader.php -> autoload() -> findFile()
/** * 查找文件 * @param $class * @return bool */ private static function findFile($class) { //以$class == 'think\Route' 为例 if (!empty(self::$map[$class])) { // 类库映射 return self::$map[$class]; } // 查找 PSR-4 $logicalPathPsr4 = strtr($class, '\\', DS) . EXT;//替换文件分隔符和后缀名 $first = $class[0];// $first = 't' if (isset(self::$prefixLengthsPsr4[$first])) {//$prefixLengthsPsr4 为二维数组,第一维以class首字母区分,第二维以t*前缀区分 foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {//遍历t*前缀 if (0 === strpos($class, $prefix)) {//找到存在于$class的前缀 foreach (self::$prefixDirsPsr4[$prefix] as $dir) {//遍历该前缀下的所有文件夹 if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) {//可以看到剔除掉前缀 return $file; } } } } } // 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) { return $file; } } // 查找 PSR-0 if (false !== $pos = strrpos($class, '\\')) {//包含/分隔符 // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS);//这里为什么不拼接后缀名??? } else {//仅包含类文件名 // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DS) . EXT;//与psr4不同的是,psr0会把类名中的下划线替换成文件分隔符 } if (isset(self::$prefixesPsr0[$first])) { foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) {//不会剔除掉前缀 return $file; } } } } } // 查找 PSR-0 fallback dirs foreach (self::$fallbackDirsPsr0 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } return self::$map[$class] = false; }
可以看到psr0和psr4处理方式很类似,主要区别在于:
psr4 在拼接文件路径时会剔除掉前缀,而 psr0不会剔除。
psr0 会将类名中的 '_' 替换成 文件分隔符。
可以看个psr4例子:
以第一个为例, 传入findFile()的$class 为 \Acme\Log\Write\File_Writer , 执行$dir . DS . substr($logicalPathPsr4, $length) 时剔除掉前缀 Acme\Log\Writer , 此时 $dir 为 ./acme-log-writer/lig/ ,拼接结果为 ./acme-log-writer/lib/File_Writer.php
如果是psr0 , 不剔除前缀,且替换下划线为文件分隔符,执行 $dir . DS . $logicalPathPsr0 结果为 ./acme-log-writer/lib/File/Writer.php。
这些差异也导致 psr4的文件路径看起来比较简洁。
相关文章推荐
- PHP规范PSR0和PSR4的理解
- PHP规范PSR0和PSR4的理解
- PHP规范PSR0和PSR4的理解
- 关于命名空间的理解---iostream与iostream.h的区别
- 关于php 命名空间 和 use not found class
- PHP中的use、命名空间、引入类文件、自动加载类的理解
- PHP 命名空间加载的理解
- PHP中的use、命名空间的理解
- 关于php命名空间的一些小细节
- 关于PHP的命名空间,简单粗暴易懂
- 关于php接口中命名空间报错问题:
- 关于Thinkphp3.2 命名空间的说明-php5.3命名空间介绍-TP自动加载
- 如何理解php中命名空间概念
- 关于《Windows核心编程 5th》“3.3.4终端服务命名空间”章节的理解
- php 命名空间 和 自动加载机制 的简单理解
- 关于PHP中命名空间和spl_autoload_register函数的关系说明
- 关于XML Schema命名空间中已经有xmlns却还要targetnamespace的理解
- PHP中的use、命名空间、引入类文件、自动加载类的理解
- PHP中的use、命名空间、引入类文件、自动加载类的理解
- PHP命名空间的理解