PSR-4 的实现示例
闭包实例
<?php
/**
* 一个具体项目实现的示例。
*
* 在注册自动加载函数后,下面这行代码将引发程序
* 尝试从 /path/to/project/src/Baz/Qux.php
* 加载 \Foo\Bar\Baz\Qux 类:
*
* new \Foo\Bar\Baz\Qux;
*
* @param string $class 完全标准的类名。
* @return void
*/
spl_autoload_register(function ($class) { // 具体项目的命名空间前缀
$prefix = 'Foo\\Bar\\'; // 命名空间前缀对应的基础目录
$base_dir = __DIR__ . '/src/'; // 该类使用了此命名空间前缀?
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
// 否,交给下一个已注册的自动加载函数
return;
} // 获取相对类名
$relative_class = substr($class, $len); // 命名空间前缀替换为基础目录,
// 将相对类名中命名空间分隔符替换为目录分隔符,
// 附加 .php
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // 如果文件存在,加载它
if (file_exists($file)) {
require $file;
}
});
类实例
<?php
namespace Example; /**
* 一个多用途的示例实现,包括了
* 允许多个基本目录用于单个
* 命名空间前缀的可选功能
*
* 下述示例给出了一个 foo-bar 类包,系统中路径结构如下……
*
* /path/to/packages/foo-bar/
* src/
* Baz.php # Foo\Bar\Baz
* Qux/
* Quux.php # Foo\Bar\Qux\Quux
* tests/
* BazTest.php # Foo\Bar\BazTest
* Qux/
* QuuxTest.php # Foo\Bar\Qux\QuuxTest
*
* ……添加路径到 \Foo\Bar\ 命名空间前缀的类文件中
* 如下所示:
*
* <?php
* // 实例化加载器
* $loader = new \Example\Psr4AutoloaderClass;
*
* // 注册加载器
* $loader->register();
*
* // 为命名空间前缀注册基本路径
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');
*
* 下述语句会让自动加载器尝试从
* /path/to/packages/foo-bar/src/Qux/Quux.php
* 中加载 \Foo\Bar\Qux\Quux 类
*
* <?php
* new \Foo\Bar\Qux\Quux;
*
* 下述语句会让自动加载器尝试从
* /path/to/packages/foo-bar/tests/Qux/QuuxTest.php
* 中加载 \Foo\Bar\Qux\QuuxTest 类:
*
* <?php
* new \Foo\Bar\Qux\QuuxTest;
*/
class Psr4AutoloaderClass
{
/**
* 关联数组,键名为命名空间前缀,键值为一个基本目录数组。
*
* @var array
*/
protected $prefixes = array(); /**
* 通过 SPL 自动加载器栈注册加载器
*
* @return void
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
} /**
* 为命名空间前缀添加一个基本目录
*
* @param string $prefix 命名空间前缀。
* @param string $base_dir 命名空间下类文件的基本目录
* @param bool $prepend 如果为真,预先将基本目录入栈
* 而不是后续追加;这将使得它会被首先搜索到。
* @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 mixed 成功时为已映射文件名,失败则为 false
*/
public function loadClass($class)
{
// 当前命名空间前缀
$prefix = $class; // 通过完整的命名空间类名反向映射文件名
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;
} // 删除 strrpos() 下一次迭代的尾部命名空间分隔符
$prefix = rtrim($prefix, '\\');
} // 找不到映射文件
return false;
} /**
* 为命名空间前缀和相关类加载映射文件。
*
* @param string $prefix 命名空间前缀
* @param string $relative_class 相关类
* @return mixed Boolean 无映射文件则为false,否则加载映射文件
*/
protected function loadMappedFile($prefix, $relative_class)
{
// 命名空间前缀是否存在任何基本目录
if (isset($this->prefixes[$prefix]) === false) {
return false;
} // 通过基本目录查找命名空间前缀
foreach ($this->prefixes[$prefix] as $base_dir) { // 用基本目录替换命名空间前缀
// 用目录分隔符替换命名空间分隔符
// 给相关的类名增加 .php 后缀
$file = $base_dir
. str_replace('\\', '/', $relative_class)
. '.php'; // 如果映射文件存在,则引入
if ($this->requireFile($file)) {
// 搞定了
return $file;
}
} // 找不到
return false;
} /**
* 如果文件存在从系统中引入进来
*
* @param string $file 引入文件
* @return bool 文件存在则 true 否则 false
*/
protected function requireFile($file)
{
if (file_exists($file)) {
require $file;
return true;
}
return false;
}
}
PSR-4 的实现示例的更多相关文章
- PHP的PSR系列规范都有啥内容
PSR 是PHP Standard Recommendation的简写,它其实应该叫PSRs,即系列推荐标准:目前通过的规范有PSR-0(Autoloading Standard).PSR-1(Bas ...
- nginx subrequest演示示例程序
只有简单subrequest应用演示示例. nginx.conf文件: #user nobody; worker_processes 1; #error_log logs/error.log; #er ...
- PHP PSR 代码风格
FIG组织在制定跟PHP相关规范,简称PSR,PSR旨在通过讨论我们代码项目的共同点以找出一个协作编程的方法. 什么是psr0 强调自动加载的方式 下文描述了若要使用一个通用的自动加载器(autolo ...
- [转帖]Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍
Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍 原文:http://blog.csdn.net/tianlesoftware/article/details/58095 ...
- PSR规范0-4整理
PSR规范 psr规范 引言: PSR 是 PHP Standard Recommendations 的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准.这些规范的目的是 ...
- php开发规范-psr系列规范
转自:http://www.cnblogs.com/x3d/p/php-psr-standards.html PSR 是PHP Standard Recommendation的简写,它其实应该叫PSR ...
- ps示例
博客PS示例 一显示指定真正用户名(RUID)或用户ID的进程 打开另外一个终端 [root@centos72 ~]# id wang uid=1000(wang) gid=1000(wang) gr ...
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...
- .NET跨平台之旅:将示例站点升级至 ASP.NET Core 1.1
微软今天在 Connect(); // 2016 上发布了 .NET Core 1.1 ,ASP.NET Core 1.1 以及 Entity Framework Core 1.1.紧跟这次发布,我们 ...
- 通过Jexus 部署 dotnetcore版本MusicStore 示例程序
ASPNET Music Store application 是一个展示最新的.NET 平台(包括.NET Core/Mono等)上使用MVC 和Entity Framework的示例程序,本文将展示 ...
随机推荐
- Java实现通过反射获取指定类的所有信息
package com.ljy; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.l ...
- 面试被问为什么使用Spring Boot?答案好像没那么简单
面试官:项目中有使用Spring Boot吗? 小小白:用过. 面试官:说一下为什么要使用Spring Boot? 小小白:在使用Spring框架进行开发的过程中,需要配置很多Spring框架包的依赖 ...
- Java笔记(day18-19)
泛型: jdk1.5出现的安全机制. 好处: 1,将运行时期的问题ClassCastException转到了编译时期. 2,避免了强制转换的麻烦. <>:当操作的引用数据类型不确定的时候. ...
- 使用elasticsearch搭建自己的搜索系统
什么是elasticsearch Elasticsearch 是一个开源的高度可扩展的全文搜索和分析引擎,拥有查询近实时的超强性能. 大名鼎鼎的Lucene 搜索引擎被广泛用于搜索领域,但是操作复杂繁 ...
- C# 数据操作系列 - 2. ADO.NET操作
0.前言 在上一篇中初略的介绍了一下SQL的基本写法,这一篇开始我们正式步入C#操作数据库的范围.通过这一系列的内容,我想大家能对于数据库交互有了一定的认识和基础.闲话不多说,先给大家介绍一个C#操作 ...
- OpenCV 3.4.2 Windows系统下的环境搭建(附带opencv_contrib-3.4.2)
前言 当前需要回到Windows平台下进行开发,在win10系统上搭建了编译opencv3.4.2的环境,并添加opencv_contrib-3.4.2的模块,以下是本文所需要的软件以及源码. 系统: ...
- Python:日薪工资计算
劳动者离职,当天要结清工资,实际操作是当天算清,三日内结清.有的公司省人力和吃利息,统一计算,统一下月月底发放. 有时要验算下离职工资,用Python操作一番,输入计时天数.请假小时.加班小时.基本工 ...
- LeetCode 102. 二叉树的层序遍历 | Python
102. 二叉树的层序遍历 题目来源:https://leetcode-cn.com/problems/binary-tree-level-order-traversal 题目 给你一个二叉树,请你返 ...
- CTR学习笔记&代码实现5-深度ctr模型 DeepCrossing -> DCN
之前总结了PNN,NFM,AFM这类两两向量乘积的方式,这一节我们换新的思路来看特征交互.DeepCrossing是最早在CTR模型中使用ResNet的前辈,DCN在ResNet上进一步创新,为高阶特 ...
- POI 导入excel数据自动封装成model对象--代码分析
上完代码后,对代码进行主要的分析: 1.主要使用反射api将数数据注入javabean对象 2.代码中的日志信息级别为debug级别 3.获取ExcelImport对象后需要调用init()方法初始化 ...