php自动加载规范 PSR4 (Thinkphp)

摘要:
PSR4是自动加载规范。旧版本是PSR0。虽然thinkPHP支持PSR4和PSR0的自动加载方法,但默认值是先加载PSR4。如果失败,请再次加载PSR0。phpnamespaceappindixcontroller;ClassIndex{}加载并传输到PSR4时,$class=appindexcontrollerIndex;假设当前根目录是:E:app当前命名空间前缀是:app根据前面的转换步骤,该类的路径应该是路径E:/app/index/controller/index.php的对角线(/)和反对角线()。

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 appindexcontroller;

class Index{
}

那么在加载的时候,传给这个PSR4的时候,$class=appindexcontrollerIndex;

假设当前的根目录为:E:app
当前的命名空间前缀为:app
根据前面的转换步骤,这个类的路径应该是在:
E:/app/index/controller/Index.php

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

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

thinkphp5的类加载

php自动加载规范 PSR4 (Thinkphp)第1张

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

而对于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)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MATLAB分布拟合工具箱distributionFitterJAVA 传输post传输长字符、数据编码解码 反序列化字符串下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

PHP获取上周、本周、上月、本月、本季度、上季度时间

echo date("Y-m-d",strtotime("now")); echo "<br>"; echo date("Y-m-d",strtotime("-1 week Monday")); echo "<br>"; echo date("Y-m-d",strtotime("-1 week Sunday")); ech...

关于PHP的 PHP-FPM进程CPU 100%的分析和解决

在以往的开发过程中,碰到过php-fpm的原因导致CPU负载过高,load 20~50,严重影响了安全和服务稳定的问题,那怎么来查看和分析问题呢?请看下文。 1. 查看是否是硬件问题   方式:top  命令   主要查看:load average(平均负载),这是一个4核8G内存的服务器   1分钟平均负载:2.32;   5分钟平均负载:2.18;...

基于php的AWS存储服务

近几天用到了aws的s3存储服务,公司内部的完全兼容aws并对其进行了封装,之前也用过,现在把经验总结一下。 既然要用,首先需要安装sdk,下边提供了几种安装方法 方法一:使用composer安装 1.先建立个安装目录,/opt/s3,本程序运行的实际工作目录是项目路径 /data/www/XXX,运行的其实是该目录下的vendor 然后进到该目录 ,下载...

LNMP环境的安装配置(简单版)

0、安装必要的依赖软件 如果已经安装了可能会进行升级,版本完全一致则不会进行任何操作。 yum -y install bzip2-devel curl-devel freetype-devel gcc libjpeg-devel libpng-devel libxslt-devel libxml2-devel openssl-devel pcre-deve...

PHP中的全局变量global和$GLOBALS的区别

1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。 但是在函数体内定义的global变量,函数体内可以使用,在函数体外定义的global变量不能在函数体内使用,具体看下面示例。 (1)在函数体内定义global变量,函数体内可以使用。 <?php...

PHP函数stream_context_create()模拟POST/GET

有时候,我们需要在服务器端模拟 POST/GET 等请求,也就是在 PHP 程序中去实现模拟,改怎么做到呢?或者说,在 PHP 程序里,给你一个数组,如何将这个数组 POST/GET 到另外一个地址呢?当然,使用 CURL 很容易办到,那么如果不使用 CURL 库,又该怎么办呢?其实,在 PHP 里已经有相关的函数实现了,这个函数就是接下来要讲的 stre...