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到底是干什么的。
这个规范主要就是将类转换成物理路径。

  1. 命名空间前缀使用根目录替换
  2. 去掉命名空间前缀剩下的部分,叫做它相对类名
  3. 使用目录分隔符替换掉相对类名中的命名空间分隔符(也就是\变成/)
  4. 加上.php

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

<?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的类加载

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

而对于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

php自动加载规范 PSR4 (Thinkphp)的更多相关文章

  1. PHP 自动加载规范PSR-4

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  2. 【PSR规范专题(5)】PSR-4 改进后的自动加载规范

    本文转自: https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 关键词 "必须"(&quo ...

  3. PHP自动加载下——PSR4

    1.先来介绍一下PSR规范 PHP-FIG,它的网站是:www.php-fig.org.就是这个联盟组织发明和创造了PSR规范,其中自动加载涉及其中两个规范,一个是PSR0,一个是PSR4, PSR0 ...

  4. PSR-4 规范实例讲解 -- php 自动加载

    参考 参考文档:https://www.kancloud.cn/thinkphp/php-fig-psr/3144 参考实例:https://github.com/php-fig/fig-standa ...

  5. 如何实现一个php框架系列文章【3】支持psr4的自动加载类

    psr4自动加载规范https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 我们把第三方使用psr规范的类库放在v ...

  6. PSR-4 自动加载器

    div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,cod ...

  7. 基于PHP规范的自动加载方式(composer配置)

    针对PHP这种编程语言,到目前FIG指定了五个规范,分别如下: PSR0:自动加载: PSR1:基本代码规范: PSR2:代码样式规范: PSR3:日志接口规范: PSR4:自动加载规范: 看上去PS ...

  8. thinkphp5.0 自动加载

    自动加载 概述 ThinkPHP5.0真正实现了按需加载,所有类库采用自动加载机制,并且支持类库映射和composer类库的自动加载. 自动加载的实现由think\Loader类库完成,自动加载规范符 ...

  9. thinkphp5.0自动加载

    概述 ThinkPHP5.0 真正实现了按需加载,所有类库采用自动加载机制,并且支持类库映射和composer类库的自动加载. 自动加载的实现由think\Loader类库完成,自动加载规范符合PHP ...

随机推荐

  1. MonolithFirst

    As I hear stories about teams using a microservices architecture, I've noticed a common pattern. Alm ...

  2. Whitelabel Error Page 专题

    Spring boot为错误视图提供了如下错误属性:timestamp:错误发生的时间status:HTTP状态码error:错误原因exception:异常的类名message:异常消息(如果这个错 ...

  3. WebJars

    WebJarsWebJars是一个很神奇的东西,可以让大家以jar包的形式来使用前端的各种框架.组件. 什么是WebJars 什么是WebJars?WebJars是将客户端(浏览器)资源(JavaSc ...

  4. 如何开始使用 Java 机器学习

    开始Java机器学习的最好工具是什么? 这个问题已经有一段时间了,但最近这些日子几乎每个人都在谈论人工智能和机器学习.这已经不再是一个保留给科学家和研究者的秘密,而是几乎实现于每一项新兴技术中. 在下 ...

  5. eclipse如何新建项目发布到git

    1.首先去查询本地git仓库地址 2.找到项目位置  删除git版本 3.更换git提交目标地址  目标地址是新建的git仓库地址 4.提交

  6. python3[爬虫实战] 使用selenium,xpath爬取京东手机

    使用selenium ,可能感觉用的并不是很深刻吧,可能是用scrapy用多了的缘故吧.不过selenium确实强大,很多反爬虫的都可以用selenium来解决掉吧. 思路: 入口: 关键字搜索入口 ...

  7. Java 读书笔记 (六) 引用类型

    Java里使用long类型的数据要在数值后面加上L,否则会作为整型解析. 引用类型 引用类型是一个对象类型,它的值是指向内存空间的引用,就是地址, 所指向的内存中保存着变量所表示的一个值或一组值. i ...

  8. bzoj3598 [Scoi2014]方伯伯的商场之旅

    数位dp,我们肯定枚举集合的位置,但是如果每次都重新dp的话会很麻烦,所以我们可以先钦定在最低位集合,dp出代价,然后再一步步找到正确的集合点,每次更改的代价也dp算就好了. #include < ...

  9. BZOJ_3524_[Poi2014]Couriers_主席树

    BZOJ_3524_[Poi2014]Couriers_主席树 题意:给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r- ...

  10. [Noi2015]软件包管理器 BZOJ4196

    分析:水题 每次安装的时候和根节点求lca的过程中区间覆盖+区间查询 每次删除的时候查询子树中安装的数量+区间覆盖 附上代码: #include <cstdio> #include < ...