深入理解composer自动加载原理

简介: 深入理解composer自动加载原理

Composer 作为 PHP 的包管理工具,为 PHPer 们提供了丰富的类库,本文来一步步剖析 Composer 的原理

从 __autoload魔术方法 到  spl_autoload_register函数

建立vendor目录,下面建立 autoload.phpTestClass.phpspl_autoload_register.php

利用__autoload实现自动加载

  • autoload.php
<?php
/**
 * Created by 憧憬.
 */
$testClass = new TestClass();
$testClass->print();
function __autoload($className)
{
    require $className . '.php';
}
  • TestClass.php
<?php
/**
 * Created by 憧憬.
 */
class TestClass
{
    public function print()
    {
        echo 'Test Class!!';
    }
}

在编写过程中,我并没有引入 TestClass.php, 但是可以利用 __autoload 这个魔术方法来进行自动引入,该方法就是在类未加载时自动触发,但是这个是之前的实现,未来可能废弃,在 php7.2 后使用 spl_autoload_register 我们来看一下

自动加载的未来: spl_autoload_register

PHPSPL库作为扩展库,其中包含很多类库,已经于5.3.0版本后默认保持开启,成为PHP的一组强大的核心扩展库。

实现自动加载

  • spl_autoload_register.php
<?php
/**
 * Created by 憧憬.
 */
spl_autoload_register(function ($className) {
    require $className . '.php';
});
$testClass = new TestClass();
$testClass->print();

是不是和__autoload()很像,当然作用也很像。我们直接运行这个文件试试,会发现TestClass.php也正常的加载了进来。那么为啥不直接用__autoload()函数,而使用sql_autoload_register()这么诡异的函数,而且还有个神奇的闭包参数!!!

PHP官方文档中的定义

注册给定的函数作为 __autoload 的实现没错

那个匿名函数就是一个__autoload()函数,我们可以理解为给当前这个PHP文件中注册一个__autoload()函数,而使用匿名函数的原因呢?当然就是为了闭包特性,最主要的就是能够带来延迟加载(懒加载 )的实现!

另外,spl_autoload_register()函数不止是仅仅去注册一个__autoload(),它实现并维护了一个__autoload()队列。原来在一个文件中只能有一个__autoload()方法,但现在,你拥有的是一个队列。

函数格式

spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] ) : bool

有点长,我们一步步看:

  • callable autoload_function:闭包函数,不多解释了,上面已经说了,不了解闭包函数的作用可以百度百度
  • bool throw:当autoload_function无法成功注册时,是否抛出异常
  • bool prepend:如果是true,将会添加一个__autoload()函数到队列的顶部
  • 这个函数有返回值,成功或失败

改造一下代码

  • CaseClass.php
<?php
/**
 * Created by 憧憬.
 */
spl_autoload_register(function ($className) {
    require_once 'TestClass' . '.php';
});
spl_autoload_register('CaseAutoLoad');
function CaseAutoLoad( $className ){
    echo "second==>\n";
    require_once 'CaseClass.php';
}
$testClass = new TestClass();
$testClass->print();
echo "还没实例化 CaseClass \n";
// 在这之前都没有执行第二个 spl_autoload_register函数 也就是利用闭包实现了懒加载
$s = new CaseClass();
$s->show();

这个函数最大的作用就是维护这个队列并且可以延迟加载我们需要的文件

查看composer的源码并实现psr4命名空间自动加载

composer init或者直接install之后,自动生成了一个vendor目录,这时您需要在文件中手动的require这个vendor目录下的autoload.php文件,便可以自动加载第三包了,其实这个文件又载入了vendor/composer/autoload_real.php

  • 进入vendor/composer/autoload_real.php
  • getLoader()方法中马上就能发现spl_autoload_register()方法
  • 并在最后看到 $loader->register(true); $loader就是 ClassLoader.php
  • 进入ClassLoader.php文件中,找到register()方法 没错,里面还是一个spl_autoload_register()方法,这样来看,这货就是Composer的灵魂啊!!

我们来看一下,因为考虑到php版本的问题,所以有多种加载方式,比如我们耳熟能详的 命名空间自动加载

vendor 下面建立目录 Model/UserModel.phpautoload_psr4.php

  • Model/UserModel.php
<?php
/**
 * Created by 憧憬.
 */
namespace Model;
class UserModel
{
    public function show()
    {
        echo 'user model!';
    }
}
  • autoload_psr4.php
<?php
/**
 * Created by 憧憬.
 */
spl_autoload_register(function ($class) {
    $file   = __DIR__ . '/' . str_replace('\\', '/', $class) . '.php';
    if (file_exists($file)) {
        require $file;
    }
});
use Model\UserModel;
$t = new UserModel();
$t->show();

这样也就实现了自动加载

autoload_real.php中,我们发现了熟悉的spl_autoload_register函数。但这个文件最大的作用是去加载ClassLoader.php这个文件和一些目录文件,也在同级目录下。在autoload_real.php中,大家可以发现在调用ClassLoader的register()函数前,还加载了几个目录相关的文件

  • autoload_static.php,静态加载方式,顶级类加载命名空间
  • autoload_psr4.php,遵守PSR4规范的包目录映射数组文件
  • autoload_namespaces.php,命名空间映射,PSR0规范
  • autoload_classmap.php,类图映射,命名空间直接映射路径

这些就对应不同的规范,使用不同的自动加载,我们可以安装一些包看一下这些源码会发生哪些改变,我安装了一个 qrcode 的包, autoload_psr4.php的内容变成了这样:


接下来,composer这个命令干了什么您应该也就了解了。当您进行composer require时,首先修改了composer.json文件,然后下载包,完成后根据包里的composer.json文件中所对应的规范来修改对应的autoload_xxx.php文件。完成了文件命名空间相关内容的映射。当register()进行加载的时候,自然就得心应手了。

参考自: 深入学习Composer原理(四) - 知乎

目录
相关文章
|
9月前
|
缓存 PHP 开发者
PHP中的自动加载机制及其优化方法
传统的PHP开发中,经常会遇到类文件加载繁琐、效率低下的情况,而PHP的自动加载机制能够很好地解决这一问题。本文将深入探讨PHP中的自动加载机制,介绍其原理及实现方式,并提出了一些优化方法,帮助开发者提升代码加载效率,提高应用性能。
|
6月前
|
测试技术 PHP 开发工具
深入解析 Laravel 中的 Composer Lock 文件
【8月更文挑战第31天】
115 0
|
PHP
PHP 文件加载简单使用
PHP 文件加载简单使用
77 0
|
JSON JavaScript Linux
作曲家composer难也不难
我为啥会写出这样的标题呢,我也停顿了一下,这不是自然而然的事么。因为composer要说起来其实不难,就是一个依赖管理工具,但要是说难,其实也挺难的,因为在安装使用的第一步就有可能踩坑,有的同学甚至直接放弃了。今天小马就和大家一起来入门一下。
92 0
作曲家composer难也不难
|
PHP
深入理解composer自动加载原理
深入理解composer自动加载原理
203 0
|
设计模式 存储 架构师
ThinkPHP5源码阅读-类的自动加载register与autoload的实现
PHP快速入门与实战ThinkPHP是国内最流行的一款PHP框架,是国人自主研发的框架,起源于2006年,经过了十几年的不断发展。已经成为了一款被PHP广泛认可的性能开发效率兼具的利器。阅读框架源码有助于我们更好的学习语言基础,拓展设计模式等相关能力。同时很多设计与编码的思想也能更好的指导我们日常工作,尤其是想成为资深程序员或者架构师方面的同事,这是一个必须要学习的过程。今天是ThinkPHP5源码第一讲,关于类的自动加载,看看源码底层是怎么实现的。怕迷路的同学,先给个关注吧。
115 0
|
缓存 Linux PHP
PHP快速入门14-Composer包管理安装与使用,附常见的20个使用例子
PHP Composer 是 PHP 的一个包管理工具,它被广泛用于 PHP 应用程序的依赖管理。Composer 可以自动查找和下载 PHP 应用所需要的第三方类库和组件,并将它们集成到应用程序中。
407 0
|
Linux PHP 开发者
Composer 镜像原理 (1) —— 初识 Composer
Composer 是一个 PHP 的依赖管理工具,它可以帮助开发者轻松地管理和维护 PHP 项目中的依赖关系。你是否好奇过它的镜像仓库是怎么实现的?本文为你揭晓。
149 0
|
PHP
PHP自动加载与composer自动加载
在面向对象的程序中,大部分的情况都是需要使用命名空间的。我们先了解命名空间的知识,在后续也会结合命名空间实现自动加载 在我们使用计算机的过程,如果想在同一个路径目录下新建两个同名的文件,将会得到错误提示,当前目录下已经存在该文件名的文件。 在php程序中也是如此,我们没办法在同一个空间下声明两个一样类名的文件,否则会得到报错提示 Cannot declare class A, because the name is already in use
112 2
PHP自动加载与composer自动加载
|
数据库连接 PHP
使用composer安装laravel-admin及其过程中遇到的坑
使用composer安装laravel-admin及其过程中遇到的坑
313 0