你所不知道 ❌ PHP 自动加载

前言

不少的小伙伴在,学习 PHP 的时候最先面对的问题之一就是 requireincluderequire_onceinclude_once 的相爱相杀。php

在了解了它们相爱相杀的故过后,每每就开始使用起了框架。框架当然是干活的好工具,可是你知道你平时 new 一个新类的时候,发生了什么吗?有想过为何咱们 遵循规范 就会自动的帮咱们作好一切的加载吗? 让咱们一切来探索发现其中的奥秘。git

时间线

蒸汽时代

PHP 代码的顶部你是否是常常看到这样的代码。github

require 'lionis.php';
require 'is.php';
require 'cool.php';

若是只是引入几个 PHP 脚本,那还能够接受。那引入成千上万个脚本的时候,爆炸是在所不免的。若是对一个脚本改了个名字,还须要对引入改脚本的每一个脚本更名,能不爆炸吗?连打出这段话都怎么绕。json

电气时代

PHP 电气时代,开始出现了 __autoloadspl_autoload_register 函数注册自定义的自动加载策略。数组

通俗的来讲,__autoloadspl_autoload_register 是一个 杀手组织,他们会去雇佣 各国杀手 (函数)。当咱们想搞定某我的的时候(new),只须要提供名字(类名),剩下的 杀手 会帮咱们搞定的。微信

__autoload

PHP 5 开始提供这个函数 传送门。当你使用的 找不到的时候,它把类名当成参数扔进这个函数。composer

<?php
// Lionis.php
class Lionis {
    public function __construct() {
        echo '欧耶耶, 我就是 Lionis';
    }
}
<?php
// index.php
function __autoload($classname) {
    $filename = './' . $classname . '.php';
    require_once $filename;
}

$lionis = new Lionis();

输出框架

欧耶耶, 我就是 Lionis
spl_autoload_register

若是咱们 项目 很大很老又或者你是一个 爱折腾 的少先队员,须要引入的东西有不同的规范,这时候若是都放在 __autoload 函数里,这个函数立刻就会膨胀的。并且 __autoload 是全局惟一的,若是被人占用了,可能会致使错误。(欲使一我的灭亡,必将先使其膨胀。)函数

PHP 5.1.2 开始提供这个函数 传送门,注册给定的函数做为 __autoload 的实现。因此,咱们看一些框架或插件在本身使用的时候,为了兼容可能会出现 function_exists(spl_autoload_register)工具

<?php
function lionisIsCoolFind($classname) {
    require './' . $classname . '.php';
}

// 函数
spl_autoload_register('lionisIsCoolFind');

// 匿名函数
spl_autoload_register(function($require) {
    require './' . $classname . '.php';
});

// 类中的函数
spl_autoload_register(array('Lionis', 'loadClass'));

欧耶,这下咱们能够写不少不一样的自动加载函数了。

信息时代

师傅当心,前面有妖气! 。若是咱们每一个人都本身实现一套自动加载的方法,每一个PHP 组件框架都使用独特的自动加载器,并且每一个框架使用不一样的逻辑加载PHP类、接口和性状。

那当咱们使用一些第三方框架的时候,还须要去弄清楚引导文件中的 自动加载器,那样是有多和 时间 过不去呢。 PHP-FIG 认识到了这个问题了,推荐使用 PSR-4 规范,来促进组件之间的 互操做性,这样咱们就可使用一个自动加载器了。

PSR-4 规范

利用命名空间的前缀和文件系统中的目录对应起来。

映射关系为

namespace    => filePath
\Lionis\Cool => cool

带有命名空间的类

<?php
// 该文件为 cool/Real.php
namespace \Lionis\Cool;

class Real {
}

建立一个对象

<?php
// 该文件为 index.php

$lionis = new \Lionis\Cool\Real;

这个时候,按照 PSR-4 的规范,自动加载器应该去加载 cool/ 目录下的 Real.php

不对!那这样不是还要本身去实现 自动加载器 嘛,否则怎么 无中生有 出现 自动加载器 呢?难道官方 内置 了?

out 了吧,咱们可使用依赖管理器 composer 来生成 PSR-4 自动加载器。你可能会疑问,那个人旧项目没有遵循 PSR-4 规范怎么办?嘿嘿,让咱们来探索发现一下 composer 是怎么解决这个问题的吧。

Composer

哦吼吼,咱们此次的重点在与探究自动加载,因此 composer 的安装和使用等,就不去讨论了。

composer 自动加载设置了 4种 加载方式

  • PSR-0
  • PSR-4
  • classmap
  • files

PSR-0

要求命名空间和目录层层对应,且可使用 _ 做为路径分隔符,可是这会致使目录结果变得过深。

composer 执行 install 等操做时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr0.php文件中的返回数组中。

例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\Love\SomeClass,PSR-0 加载的实际目录为 vendor/Lionis/IsReal/Cool/Very/Good/Love/SomeClass.php。

对吧,这简直深得吓人,因此 PSR-0 被官方废除了。可是一些主流的框架已经实现了 PSR-0,为了向下兼容仍是要实现 PSR-0

composer.json配置:

"autoload": {
    "psr-0": {
        "Very\\Good": "vendor\Lionis\IsReal\Cool"
    }
}

PSR-4

PSR-4 是如今比较推荐的方法,用于替代 PSR-0
PSR-0 不一样的是,取消掉了 _ 做为分隔符和目录结构。

composer 执行 install 等操做时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr4.php文件中的返回数组中。

例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\
Love\SomeClass,PSR-4 加载的实际目录为 vendor/Lionis/IsReal/Cool/Love/SomeClass.php。

composer.json配置:

"autoload": {
    "psr-4": {
        "Very\\Good": "vendor\Lionis\IsReal\Cool"
    }
}

classmap

classmap 经过配置指定的目录和文件,在 composer 执行 install 等操做时,composer 会去扫描对应的目录下以.php结尾的文件中的 class,并存储在 vendor/composer/autoload_classmap.php文件中的返回数组中。

composer.json配置:

"autoload": {
    "classmap": [
        "Lionis/",
        "Xiaoer/"
    ]
}

若是 Lionis 下有一个叫 VeryCool的文件,那么在vendor/composer/autoload_classmap.php 中会生成。

<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'VeryCool' => $baseDir . '/Lionis/VeryCool.php',
    // 其余的映射
);

files

files 就是直接简单粗暴的加载文件。在 composer 执行 install 等操做时,composer 会把文件中的配置存储在 vendor/composer/autoload_static.php文件中的生成一个 $files 数组。

composer.json 配置:

"autoload": {
    "files": ["Lionis/Very/Cool.php"]
}

小结

composer 经过使用 composer.json,用 json 的格式来指定咱们须要自动加载规则。咱们只要在入口文件引入 vendor/autoload.php 就能很方便的便能使用 自动加载

若是你对 composer 实现 自动加载 的原理感兴趣,能够顺着 vendor 中的 autoload.php 去看看源码。

总结

石器时代信息时代PHP 经历了不少试验和改变后正在变得愈来愈好。固然,许多优秀的框架让咱们开发速度更快,须要理解的一些知识点也随之被隐藏起来,让咱们更加专一于实现逻辑。可是,咱们有的时候仍是要尝试的去理解他们工做的原理,来提高咱们本身。像我老师说过的,所不定一会儿踩到狗屎运了呢。

更多

细说 PHP 类库自动加载

一块儿成长

在困惑的城市里总少不了并肩同行的 伙伴 让咱们一块儿成长。
  • 若是您想让更多人看到文章能够点个 点赞
  • 若是您想激励小二能够到 Github 给个 小星星
  • 若是您想与小二更多交流添加微信 m353839115

微信公众号

本文原稿来自 PushMeTop
相关文章
相关标签/搜索