1.先来介绍一下PSR规范

PHP-FIG,它的网站是:www.php-fig.org。就是这个联盟组织发明和创造了PSR规范,其中自动加载涉及其中两个规范,一个是PSR0,一个是PSR4, PSR0规范已经过时了,官方有提示,现在主要是用PSR4规范定义自动加载标准。

2.PRS4简介

这个 PSR 描述的是通过文件路径自动载入类的指南;它作为对 PSR-0 的补充;根据这个 指导如何规范存放文件来自动载入;
术语「类」是一个泛称;它包含类,接口,traits 以及其他类似的结构;

完全限定类名应该类似如下范例:

()*
完全限定类名必须有一个顶级命名空间(Vendor Name);
完全限定类名可以有多个子命名空间;
完全限定类名应该有一个终止类名;
下划线在完全限定类名中是没有特殊含义的;
字母在完全限定类名中可以是任何大小写的组合;
所有类名必须以大小写敏感的方式引用;

当从完全限定类名载入文件时:

在完全限定类名中,连续的一个或几个子命名空间构成的命名空间前缀(不包括顶级命名空间的分隔符),至少对应着至少一个基础目录。
在「命名空间前缀」后的连续子命名空间名称对应一个「基础目录」下的子目录,其中的命名 空间分隔符表示目录分隔符。子目录名称必须和子命名空间名大小写匹配;
终止类名对应一个以 .php 结尾的文件。文件名必须和终止类名大小写匹配;
自动载入器的实现不可抛出任何异常,不可引发任何等级的错误;也不应返回值;

完全限定类名 命名空间前缀 基础路径 完全路径
\Acme\Log\Writer\File_Writer Acme\Log\Write ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php
\Aura\Web\Response\Status Aura\Web /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
\Symfony\Core\Request Symfony\Core ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
\Zend\Acl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php

大家注意看第二列和第四列,命名空间前缀对应基础路径,命名空间前缀之后的子命名空间必须对应代码目录(类名必须是PHP文件)

3.优化自动加载方法

上一节中封装自动加载的方法比较简单,无法自动加载带命名空间的类

spl_autoload_register(function ($class) {// 命名空间前缀$prefix = 'Foo\\Bar\\';// 命名空间前缀对应的基础目录$base_dir = __DIR__ . '/src/';// 检查new的类是否有命名空间前缀$len = strlen($prefix);if (strncmp($prefix, $class, $len) !== 0) {return;}// 获取去掉命名空间前缀后的类名$relative_class = substr($class, $len);// 将命名空间的中的分隔符替换为目录分隔符,再加上基础目录和.php后缀,最终拼接成// 文件路径$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';// 如果文件存在则requireif (file_exists($file)) {require $file;}
});

但是上面的方法只能适用固定的命名空间前缀,不能通用。

4、再次优化通用自动加载方法

<?php
namespace Example;/*** 下面这个例子实现了一个命名空间前缀对应多个基础目录** 现在我们的目录结构是下面这样:**     /demo/autoload/*          controller/*             DemoController.php              # Foo\Bar\DemoController*             Admin/*                 AdminController.php         # Foo\Bar\Admin\AdminController*          model/*             DemoModel.php                   # Foo\Bar\DemoModel*             Admin/*                 AdminModel.php              # Foo\Bar\Admin\AdminModel** Foo\Bar分别对应基础路径 /demo/autoload/controller 和 /demo/autoload/model*/
class Psr4AutoloaderClass
{/*** 一个数组,key为命名空间前缀,值为基础路径** @var array*/protected $prefixes = array();/*** 封装自动加载函数** @return void*/public function register(){spl_autoload_register(array($this, 'loadClass'));}/**** 添加一个基础路径对应一个命名空间前缀** @param string $prefix 命名空间前缀.* @param string $base_dir 命名空间类文件的基础路径* @param bool true为往数组头部添加元素,false为往数组尾部添加元素* @return void*/public function addNamespace($prefix, $base_dir, $prepend = false){// 去掉左边的\$prefix = trim($prefix, '\\') . '\\';// 规范基础路径$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';// 初始化数组if (isset($this->prefixes[$prefix]) === false) {$this->prefixes[$prefix] = array();}// 将命名空间前缀和基础路径存入数组if ($prepend) {array_unshift($this->prefixes[$prefix], $base_dir);} else {array_push($this->prefixes[$prefix], $base_dir);}}/*** 真正包含文件方法,将给到类名文件包含进来** @param string $class 全限定类名(包含命名空间).* @return 成功将返回文件路径,失败则返回false*/public function loadClass($class){$prefix = $class;//查找$prefix最后一个\的位置,看看最后一个\之前的字符串是否在$this->prefixes中//如果不存在则继续查询上一个\的位置,获取上一个\之前的字符串是否在$this->prefixes中//如果循环结束还是没有找到则返回falsewhile (false !== $pos = strrpos($prefix, '\\')) {$prefix = substr($class, 0, $pos + 1);$relative_class = substr($class, $pos + 1);$mapped_file = $this->loadMappedFile($prefix, $relative_class);if ($mapped_file) {return $mapped_file;}//去掉右边的\$prefix = rtrim($prefix, '\\');}return false;}/*** 如果参数中的$prefix在$this->prefixes中存在,那么将循环$this->prefixes[$prefix]里的value(基础路径)* 之后拼接文件路径,如果文件存在将文件包含进来** @param string $prefix 命名空间前缀.* @param string $relative_class 真正的类名(不包含命名空间路径的类名).* @return mixed 包含成功返回文件路径,否则返回false*/protected function loadMappedFile($prefix, $relative_class){// 检查数组中是否有$prefix这个keyif (isset($this->prefixes[$prefix]) === false) {return false;}// 将数组中所有的基础路径中的文件包含进来foreach ($this->prefixes[$prefix] as $base_dir) {// 拼接文件绝对路径$file = $base_dir. str_replace('\\', '/', $relative_class). '.php';// 如果文件存在则包含进来if ($this->requireFile($file)) {// 返回文件路径return $file;}}// 没有找到文件return false;}/***如果文件存在则包含进来.** @param string $file 文件路径.* @return bool*/protected function requireFile($file){if (file_exists($file)) {require $file;return true;}return false;}
}

转载于:https://www.cnblogs.com/scofi/p/7522131.html

PHP自动加载下——PSR4相关推荐

  1. Android复习06【网络编程提高篇-安装GsonFormat、HttpUrlConnection封装、线程池、GsonFormat解析Json、自动加载下一页、自定义组件、页头页尾刷新、侧滑删除】

    2020-04-07 星期二 [第8周] [考试不考...] 目   录 思维导图 安装GsonFormat插件 添加网络访问权限 GitHub---HttpUrlConnection封装 线程池 G ...

  2. html超出高度自动下一页,上滑web页面自动加载下一页

    移动端常常是通过向上滑动到页面底部自动加载下一页内容,而不是点击"下一页"按钮进行加载.这是一个演示了自动加载下一页的小demo. html: html> 向上滑动自动加载后 ...

  3. android 自动加载下一页,Android PullToRefresh下拉到底部自动加载下一页

    有时候我们想要修改pullToRefresh直接拉到底部的是否自动加载下一页的东西这里有个方法可以供大家参考 private void scrollToBottom() { mListView.set ...

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

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

  5. html底部自动加载下一页,js页面滚动到底部时自动加载下一页数据

    一段滚动到页面底部自动加载更多数据的js代码,需要jquery.js . jquey.tmpl.js 支持 var Data = { PageCount: 1, PageSize: 30, IsCom ...

  6. 你不知道的composer自动加载

    2019独角兽企业重金招聘Python工程师标准>>> 我们都知道Composer是现代PHP框架(Yii2.Laravel...)的基石,有了Composer后我们开发是一件多么的 ...

  7. Composer自动加载(一)

    我的个人博客:逐步前行STEP Composer是PHP的基于项目的依赖管理工具,它本身集成一个autoloader,支持PSR-4,PSR-0,classmap,files 四种自动加载方式. #首 ...

  8. ios 平滑移动view_iOS 关于列表上拉(平滑加载数据)自动加载数据的问题

    项目需求 我的的列表需要改变,原来的分页加载采用的是MJRefresh框架进行加载更多数据,这需要有一个上拉动作才能触发,而我的产品的意思是当快要滑动到底部时自动加载下一页数据.我自己看了一下,发现很 ...

  9. PHP PSR4自动加载代码赏析

    转载地址:https://www.cnblogs.com/wangmy/p/6692970.html 第一部分是引入自动加载配置文件 1.入口文件:autoload.php 里面没什么东西,就是导入C ...

最新文章

  1. Java函数式折叠,循环,记忆化效率初识
  2. c/c++程序员的技术栈
  3. Python开发以太坊智能合约指南(web3.py)
  4. LeetCode Valid Sudoku
  5. format 函数包含_Python成为专业人士笔记-高级对象Format格式化
  6. DSAPI多功能组件编程应用-HTTP监听服务端与客户端
  7. 【Flink】Flink network netty ProducerFailedException SimpleChannelInboundHandler NullPointerException
  8. 木兰编程语言重现——支持列表操作,演示编辑器高亮
  9. springmvc 异常001---在SpringMVC中使用@RequestBody注解处理json时,报出HTTP Status 415的解决方案
  10. 【340天】我爱刷题系列099(2018.01.11)
  11. MongoDB配置主从同步(二)
  12. 基于MATLAB的疲劳检测系统研究解析
  13. 其他 - 所有中文字 附 拼音
  14. llvm安装方式_LLVM 安装教程(包安装)
  15. VTK实现多个体数据映射到一起进行渲染
  16. 典型问题分析——三方应用网络异常分析方法
  17. nyoj_71 独木舟上的旅行
  18. java实现记账本功能_java基础实战项目一:实现家庭记账本的简易记账功能
  19. 探寻红色印记,传承红色基因
  20. 用python将txt文件中的内容导入到excel文件中

热门文章

  1. python大数据招聘信息_2017招聘大数据丨Python需求增速达174%,AI人才缺口超百万!...
  2. 《计算机组成原理》BCD码 8421编码原理剖析
  3. ctfshow-WEB-web10( with rollup注入绕过)
  4. R 梯度提升算法①
  5. 路由协议管理距离汇总
  6. 移动互联网时代,学iOS开发好吗
  7. ASP.NET MVC呼叫WCF Service的方法
  8. Dallas CTP3 发布通告
  9. 奇偶个数 中国大学生mooc 翁恺 C语言
  10. linux glibc安装mysql_Linux安装MySQL-5.6.24-1.linux_glibc2.5.x86_64.rpm