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'; // 如果文件存在则require
if (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中
//如果循环结束还是没有找到则返回false
while (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这个key
if (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 (Thinkphp)

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

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

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

  3. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  4. 移动端上拉加载下拉刷新插件-mescroll.js插件

    官网地址是:http://www.mescroll.com // 初始化mescroll function initMeScroll() { //创建MeScroll对象,内部已默认开启下拉刷新,自动 ...

  5. Python3从零开始爬取今日头条的新闻【三、滚动到底自动加载】

    Python3从零开始爬取今日头条的新闻[一.开发环境搭建] Python3从零开始爬取今日头条的新闻[二.首页热点新闻抓取] Python3从零开始爬取今日头条的新闻[三.滚动到底自动加载] Pyt ...

  6. PHP 自动加载

    回顾 开始的时候, 如果想在一个php文件中使用其它文件的类或方法, 需要通过include/require方法将文件包含进来. 这种方法的缺点也很明显: 如果需要引入很多文件, 就需要很多的incl ...

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

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

  8. 遵循PSR-4的自动加载

    一.简介 首先这里要了解PSR,Proposing a Standards Recommendation(提出标准建议)的缩写,就是一种PHP开发规范,让我们研发出来的代码更合理.更好维护.可读性更高 ...

  9. PSR-4 自动加载器

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

随机推荐

  1. (转)USB 基本知识

    USB的重要关键字: 1.端点:位于USB设备或主机上的一个数据缓冲区,用来存放和发送USB的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性(如输入端点.输出端点.配置端点.批量传输端点) ...

  2. Java线上应用故障之CPU占用高排查与定位

    最近线上频繁报警CPU空闲不足,故紧急排查后分享给大家 1.使用top命令,获取占用CPU最高的进程号 2.查看线程号对应的进程信息 命令:ps -ef|grep 22630 3.查看进程对应的线程信 ...

  3. SQLserver连接本地服务器

    1.打开SQLserver “连接到服务器” 2.服务器类型:数据库引擎 3.服务器名称:浏览更多->本地服务器->数据库引擎->选择本地服务器 4.身份验证:windows验证 5 ...

  4. Machine Learning系列--归一化方法总结

    一.数据的标准化(normalization)和归一化 数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间.在某些比较和评价的指标处理中经常会用到,去除数据的单位限 ...

  5. discuz伪静态设置

        Discuz! 通用伪静态 -包含所有类型主机本人找了一下午才找到的,谢谢这位原创者,发出来让大家用. 第一步:打开后台  全局 SEO设置 全部打勾<ignore_js_op>  ...

  6. SilverLight 浏览器出现滚动条

    照网上说的很多解决方案要不得,最后想了下,直接在body上面加 style="overflow:hidden"解决问题,真觉得微软管理混乱,很多它自己的东西都不支持了.

  7. java基础16 捕获、抛出以、自定义异常和 finally 块(以及关键字:throw 、throws)

    1.异常的体系 /* ------|Throwable:所有异常和错误的超类 ----------|Error(错误):错误一般用于jvm或者硬件引发的问题,所以我们一般不会通过代码去处理错误的 -- ...

  8. Hadoop(七)YARN的资源调度

    一.YARN 概述 YARN 是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操 作系统平台,而 MapReduce 等运算程序则相当于运行于操作系统之上的应用程序 YARN ...

  9. Python全栈开发之3、数据类型set补充、深浅拷贝与函数

    转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5466082.html 一.基本数据类型补充 set是一个无序而且不重复的集合,有些类似于数学中的集合,也可以求交集, ...

  10. shell-sed命令详解(转)

    (转自http://blog.csdn.net/wl_fln/article/details/7281986) Sed简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时 ...