php+psr4和自动加载,php自动加载规范 PSR4 (Thinkphp)

PSR4是一种自动加载规范,老版本是PSR0,尽管thinkPHP支持PSR4和PSR0的自动加载方式,但是默认也是优先进行PSR4加载,如果失败,再进行PSR0的加载。本篇文章只会讨论PSR4的加载。

代码示例:

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到底是干什么的。

这个规范主要就是将类转换成物理路径。

命名空间前缀使用根目录替换

去掉命名空间前缀剩下的部分,叫做它相对类名

使用目录分隔符替换掉相对类名中的命名空间分隔符(也就是\变成/)

加上.php

比如thinkphp典型的一个控制器:Index.php

namespace app\index\controller;

class Index{ }

那么在加载的时候,传给这个PSR4的时候,$class=app\index\controller\Index;

假设当前的根目录为:E:\app

当前的命名空间前缀为:app

根据前面的转换步骤,这个类的路径应该是在:

E:/app/index/controller/Index.php

路径的斜杆(/)跟反斜杆(\)。在windows中通常是使用反斜杆作为路径分隔符的,而在linux中,通过是使用斜杆作为路径分隔符的。不过windows现在的API都支持使用斜杆作为路径分隔符了,而如果使用反斜杆的话,那么在单引号中,还需要写成\才能当成\。而linux中是使用/,因此我们的路径表示便是使用斜杆了。

有同学跟我反映说,php单引号不是不会被转义吗?这个确实是,不过对于要输出单引号,因此在单引号字符串中,单引号是需要使用反斜杆转义才能输出的,而反斜杆本身也是需要使用反斜杆来转义,对于其他的转义,就真的不会了。

thinkphp5的类加载

a1b2cc5cbd6b0b5d874284f131bdac7b.png

类库映射实际上就是保存一个键值对数组,键值为类名,值为物理路径,这样当类加载的时候,直接查找该数组就行。

而对于PSR4,我们根据上面知道,需要注册根目录跟命名空间前缀。

在thinkphp中注册了五个命名空间前缀:

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的备选目录

当使用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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值