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的示例程序,本文将展示 ...
随机推荐
- Prime Path素数筛与BFS动态规划
埃拉托斯特尼筛法(sieve of Eratosthenes ) 是古希腊数学家埃拉托斯特尼发明的计算素数的方法.对于求解不大于n的所有素数,我们先找出sqrt(n)内的所有素数p1到pk,其中k = ...
- SpringCloud (一) :微服务架构
什么是微服务架构 简而言之,微服务架构风格就是将单一应用的开发分为多个小的服务,每个小的服务在自己的进程中运行并使用轻量级机制进行通信(通常是一个HTTP API源),这些服务围绕业务性能进行构建,并 ...
- Qt线程池
说明 Qt中可以有多种使用线程的方式: 继承 QThread,重写 run() 接口: 使用 moveToThread() 方法将 QObject 子类移至线程中,内部的所有使用信号槽的槽函数均在线程 ...
- 写了shell脚本想一键启动三台虚拟机的Zookeeper,却不知道为啥总是启动不了
首先,一键启动的shell脚本是这样的 #! /bin/bash case $1 in "start"){ for i in node01 node02 node03 do ssh ...
- md5函数
0x01 <?php error_reporting(0); $flag = 'flag{test}'; if (isset($_GET['username']) and isset($_GET ...
- PAT 1007 Maximum Subsequence Sum (25分)
题目 Given a sequence of K integers { N1 , N2 , ..., NK }. A continuous subsequence is define ...
- 【Leetcode】1340. Jump Game V 【动态规划/记忆性搜索】
Given an array of integers arr and an integer d. In one step you can jump from index i to index: i + ...
- CPU 多核指令 —— WFE 原理【原创】
转自:http://tinylab.org/arm-wfe/ Zhang Binghua 创作于 2020/05/19 打赏 微信公众号 知识星球 关注 @泰晓科技 与数千位一线 Linux 工程 ...
- HTML5新特性-- -定时器
一.定时器:一次性定时器/周期性定时器 #requestAnimationFrame 智能定时器 #此定时器主要使用范围:动画和游戏中 特点: setTimeout(fn,500); setInter ...
- nginx配置之站点服务请求功能配置
站点服务请求功能配置:html/ nginx.conf中的http{}中的server{}: server { listen 85; server_name localhost; #charset k ...