闭包实例

<?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 的实现示例的更多相关文章

  1. PHP的PSR系列规范都有啥内容

    PSR 是PHP Standard Recommendation的简写,它其实应该叫PSRs,即系列推荐标准:目前通过的规范有PSR-0(Autoloading Standard).PSR-1(Bas ...

  2. nginx subrequest演示示例程序

    只有简单subrequest应用演示示例. nginx.conf文件: #user nobody; worker_processes 1; #error_log logs/error.log; #er ...

  3. PHP PSR 代码风格

    FIG组织在制定跟PHP相关规范,简称PSR,PSR旨在通过讨论我们代码项目的共同点以找出一个协作编程的方法. 什么是psr0 强调自动加载的方式 下文描述了若要使用一个通用的自动加载器(autolo ...

  4. [转帖]Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍

    Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍 原文:http://blog.csdn.net/tianlesoftware/article/details/58095 ...

  5. PSR规范0-4整理

    PSR规范 psr规范 引言: PSR 是 PHP Standard Recommendations 的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准.这些规范的目的是 ...

  6. php开发规范-psr系列规范

    转自:http://www.cnblogs.com/x3d/p/php-psr-standards.html PSR 是PHP Standard Recommendation的简写,它其实应该叫PSR ...

  7. ps示例

    博客PS示例 一显示指定真正用户名(RUID)或用户ID的进程 打开另外一个终端 [root@centos72 ~]# id wang uid=1000(wang) gid=1000(wang) gr ...

  8. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  9. .NET跨平台之旅:将示例站点升级至 ASP.NET Core 1.1

    微软今天在 Connect(); // 2016 上发布了 .NET Core 1.1 ,ASP.NET Core 1.1 以及 Entity Framework Core 1.1.紧跟这次发布,我们 ...

  10. 通过Jexus 部署 dotnetcore版本MusicStore 示例程序

    ASPNET Music Store application 是一个展示最新的.NET 平台(包括.NET Core/Mono等)上使用MVC 和Entity Framework的示例程序,本文将展示 ...

随机推荐

  1. Shell脚本(四)数组

    平时写脚本还没有用到过数组,暂时先记录下用法. #!/bin/bash array1=( ) array1_length=${#array1[@]} echo "array1 length: ...

  2. IoTClient开发6 - S7-200SmarTcp协议客户端实现

    环境和工具 服务端电脑IP:192.168.1.130 客户端电脑IP:192.168.1.120 1.在服务端电脑运行IoTClientTool 2.运行Wireshark 3.在客户端电脑运行Io ...

  3. tp5中使用ueditor编辑器保存文本到数据库后回显后显示html标签问题解决办法

    在编辑器ueditor中获取文本,保存到到数据库后为 当在数据库中提取出来,在显示回ueditor编辑器时候,出了问题, html标签都显示出来了 百度了下别人的解决办法是,使用官方提供的api 可是 ...

  4. 王颖奇 20171010129《面向对象程序设计(java)》第十五周学习总结

    实验十五  GUI编程练习与应用程序部署 实验时间 2018-12-6 学习总结: 理论部分: ◼ JAR文件◼ 应用程序首选项存储◼ Java Web Start JAR文件: 1.Java程序的打 ...

  5. jQuery中val() text()和html()的区别

    2020年4月21日 16:48:11 jQuery 学习 html() 它可以设置和获取起始标签和结束标签中的内容. 跟 dom 属性 innerHTML 一样.text() 它可以设置和获取起始标 ...

  6. 【Hadoop离线基础总结】MapReduce倒排索引建立

    MapReduce倒排索引建立 求某些单词在文章中出现多少次 有三个文档的内容,求hello,tom,jerry三个单词在其中各出现多少次 hello tom hello jerry hello to ...

  7. [工具]微软的学习平台Microsoft Learn很好用,推荐一下

    1. 什么是Microsoft Learn Microsoft Learn是微软这两年大力推广的全新学习平台,可提供 Microsoft 产品交互式学习体验.基本上无需登录即可使用,但登录后可以使用更 ...

  8. linux-设置代理和取消代理

    设置代理: export http_proxy="http://proxy-XXXXX" export https_proxy="https://proxy-XXXXX: ...

  9. Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决

    SpringBootLean 是对springboot学习与研究项目,是根据实际项目的形式对进行配置与处理,欢迎star与fork. [oschina 地址] http://git.oschina.n ...

  10. Mockito如何mock一条链式调用

    在写单元测试的时候,不免可能需要mock一些对象出来,并且mock一些方法调用去返回一个自己想要的对象.一般的使用是这样的: FinalPumpkin pumpkin = mock(FinalPump ...