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

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

  1. PHP自动加载下——PSR4

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. Composer自动加载(一)

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

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

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

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

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

最新文章

  1. Kubernetes最佳实践S01E05:如何优雅地终止
  2. C# String部分方法的例子StringBuilder的简单介绍
  3. Python str类型方法实例概述及常用方法——04
  4. OpenCV使用F变换过滤
  5. YII2操作mongodb笔记(转)
  6. 巧用PowerShell维护Win2008服务器作业
  7. SQLServer2008-镜像数据库实施手册(双机)SQL-Server2014同样适用
  8. python 日志内容提取
  9. CREO - 基础3 - 用拉升的方法构建一个双轮胎模型
  10. tfs 安装mysql.h_如何在centos5或centos7上编译安装tfs rcserver 模块?
  11. boss直聘一句话介绍优势_第一批被安永淘汰的00后实习生,就因为自我介绍说了这一句话!...
  12. 体检导检系统服务器系统,全科智能导检系统
  13. Spring 缓存大法
  14. iOS开发捷径学习(一)
  15. dp - 3维背包(东四省)
  16. C#控件的事件(鼠标单击等)没反应?
  17. 人民币对美元汇率中间价报6.7941元 下调139个基点
  18. 如何用python绘制等边三角形_python叠加等边三角形的代码编写方法
  19. markdown左对齐
  20. fadeIn fadeOut

热门文章

  1. Deepin在matlab的安装
  2. C语言中错误c213是什么意思,DS1302的错误:error c213
  3. 封装系统驱动放哪里啊_MPS做一体化电机驱动方案有三大绝招
  4. python scipy库函数solve用法_python scipy linalg.solve_banded用法及代码示例
  5. python字典练习_python字典练习
  6. html compiler注册机,XXX计算器1.8注册分析和注册机代码
  7. 创造思维方法训练_数学思维方法训练课程:每日一题11.23
  8. 【POJ2007】Scrambled Polygon(点集逆时针排序--极角排序/凸包--只适用于凸多边形)
  9. 【HDU5869】Different GCD Subarray Query(求[L,R]内有多少个不同的区间gcd---树状数组+思维)
  10. 【线段树入门题目集】