说明:本文主要以Laravel的容器类Container为例做简单说明Composer的自动加载机制。

Composer的自动加载机制

1、初始化一个composer项目

在一个空目录下composer安装Laravel的容器Container包:

composer require illuminate/container

然后在该目录下新建一个index.php文件,然后分析下Container类为何能被实例化:

<?php
/**
* Created by PhpStorm.
* User: liuxiang
* Date: 16/5/12
* Time: 19:59
*/
require_once __DIR__.'/vendor/autoload.php'; $container = new Illuminate\Container\Container();
var_dump($container);

2、分析下composer加载类的流程

使用composer最大的好处是只需最开始require一个autoload.php文件,就可以new你所需要的类了,不再需要传统的方式A文件内各种include跳到B文件又各种include,非常头疼。

Composer按照四种规范来加载文件:

  • psr-4
  • psr-0(这种规范某些部分不是很优雅)
  • classmap(命名空间和文件路径的映射)
  • files

ComposerAutoloaderInit88609474169d8656473fa0223c682a7a这个类是composer为了防止类冲突搞了一个命名ComposerAutoloaderInit+hash,不管咋样,require_once这个类后需要返回的是一个加载器$loader,而这个加载器经过四种规范遍历后,由null被填充为含有各种变量值的ClassLoader对象。

如果仔细观察autoload_classmap.php、autoload_namespaces.php、autoload_psr4.php和autoload_files(这里用了Container包是没有这个文件的,但Laravel整个项目是有的)文件后,这些都按照对应的规范返回要么命名空间与路径的映射,要么完整路径与某个哈希的映射。

从上图中能看出这个composer初始化路径的流程,重点是ClassLoader这个类的loadClass($class)这个方法,是通过spl_autoload_register这个PHP自动加载函数来注册到autoload函数栈中,最后返回一个$loader加载器,而这个加载器是包含一些私有变量的,由于本Container包只包含Illuminate\Container和Illuminate\Contracts,且都是psr-4规范,则私有变量$prefixLengthsPsr4和$prefixDirsPsr4就包含了命名空间路径映射的数组值,其余私有变量就是空。

最后返回一个加载器$loader,然后需要实例化一个类时,就会根据loadClass($class)来寻找对应的文件,看下文。

Container类的实例化过程#

$loader这个加载器已经有了,而且它还是塞满了各种私有变量,这些变量值为命名空间路径映射或者路径哈希映射等,当然这里只有命名空间路径映射这种psr-4规范了。也就是说,一句require_once这个autoload.php文件后就拿到了一个饱满的$loader,然后现在开始new一个类Container,那如何找到这个Container.php文件路径的呢?

从第二个序列图就可看出,首先调用ClassLoader中的loadClass()这个函数来找文件路径,传入的$class变量值是“Illuminate\Container\Container”这个字符串,然后又继续调用findFile($class)函数先做classmap查找,然后进入findFileWithExtension($class,'.php')中做psr-4/psr-0查找,其实就是搜寻这些私有变量值,比如这里Container类是psr-4规范,那就去$prefixLengthsPsr4/$prefixDirsPsr4这些psr-4私有变量中查找文件绝对路径,返回一个$file,再include下就等于这个类可以被实例化了。当然,这里Container.php文件绝对路径被找到后,发现它还实现了一个接口ContractContainer,那就再去同样方式找这个文件:psr-4根据命名空间Illuminate\Contracts\Container\Container去找这个接口对应的绝对路径。

总之,当实例化一个类时,这个$loader就去根据四种规范找该文件的绝对路径,如果这个类还有继承或实现关系,那就递归找。

自定义一个类文件#

现在自己写一个类文件,当实例化的时候,然后让composer来自动加载,怎么做?

修改composer.json文件:

{
"require": {
"illuminate/container": "^5.2"
},
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
}

这里按照psr-4规范来,然后在项目根目录下使用命令:

composer install

发现autoload_psr4.php文件会多一个数组值:

return array(
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'Illuminate\\Container\\' => array($vendorDir . '/illuminate/container'),
'App\\' => array($baseDir . '/app'),
);

然后在项目根目录下新建文件:

// app/Test/Test.php文件
<?php
/**
* Created by PhpStorm.
* User: liuxiang
* Date: 16/5/12
* Time: 21:52
*/ namespace App\Test; class Test
{
public function index()
{
echo "This is a custom class which will be autoload by composer\n";
}
}

在index.php文件中就可以实例化Test类并调用其对象函数了:

require_once __DIR__.'/vendor/autoload.php';

//$container = new Illuminate\Container\Container();
//var_dump($container); $test = new App\Test\Test();
$test->index();

终端执行输出:

通过在Composer中注册下,Composer就可以帮我们找到类文件,就不需要自己各种include,只需开始一句require_once就行,真的很方便。

One More Thing...

配置Xdebug。强烈推荐在自己的IDE中配置Xdebug,作者使用PHPStorm,并配置了Xdebug,这会提高阅读源码的效率。具体操作流程可以谷歌文档,应该很多,Netbeans或者ZendStudio应该也有很多配置文档。如果有配置不成功的,可以在本文留言下问题,作者会尽量解答。

PlantUML插件的安装。本文UML序列图用的是PlantUML这个插件来做的,还比较好用,推荐下。可以在PHPStorm插件库里搜UML就行,然后新建一个文件时会发现多了好几个UML选项,并且还有一个PlantUML窗口:

关于这个PlantUML有一篇文章还挺好:Create Beautiful UML Diagrams in Minutes from the JetBrains IDE,还有它的官网(就是有各种广告):PlantUML

总结:本文主要聊了下Composer的加载流程,并以Laravel的Illuminate\Container包为例具体说明实例化类时是如何找到其文件的,并讲述如何自定义自己的类并通过Composer来注册和加载。过两天还想结合PHP的字符串和数组这些基础知识新开篇章,到时见。

Laravel 学习笔记之 Composer 自动加载的更多相关文章

  1. [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading

    上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔 ...

  2. lumen之composer自动加载

    composer作为PHP的包管理工具,让PHP可以使用命名空间, 载入对应的类文件,不用理会文件引入的路劲问题,代码可读性也大大提高 composer 自动加载 composer 自动加载的规则 v ...

  3. Flutter学习笔记(19)--加载本地图片

    如需转载,请注明出处:Flutter学习笔记(19)--加载本地图片 上一篇博客正好用到了本地的图片,记录一下用法: 首先新建一个文件夹,这个文件夹要跟目录下 然后在pubspec.yaml里面声明出 ...

  4. composer 自动加载(php-amqplib)

    最近要使用RabbitMQ 做消息队列,也是刚接触到.因为用的的TP框架,comoser又下载不下来,所以只能手动下载拓展包,做手动加载,在php-amqplib是我手动下载下来的拓展包,创建一个co ...

  5. composer 自动加载一 通过file加载

    github地址 https://github.com/brady-wang/composer composer init 可以生成一个composer.json文件 { "name&quo ...

  6. Composer 自动加载(autoload)机制

    自动加载的类型 总体来说 composer 提供了几种自动加载类型 classmap psr-0 psr-4 files 这几种自动加载都会用到,理论上来说,项目代码用 psr-4 自动加载, hel ...

  7. composer自动加载一个文件后必须执行命令composer dump-autoload

    "autoload": { "classmap": [ "database" ], "psr-4": { "A ...

  8. composer 自动加载源码解析

    一直在用 composer,最近想看一下具体的原理是什么,就仔细阅读了一下源码,一下是个人理解.在看该文章前最好了解一下 PSR-4 自动加载规范 引入类自动加载文件 # 加载类自动加载文件 requ ...

  9. composer 自动加载 通过classmap自动架子啊

    https://github.com/brady-wang/composer github地址 composer加载自己写的类 放入一个目录下 更改composer.json "autolo ...

随机推荐

  1. Servlet 国际化

    在我们开始之前,先来看看三个重要术语: 国际化(i18n):这意味着一个网站提供了不同版本的翻译成访问者的语言或国籍的内容. 本地化(l10n):这意味着向网站添加资源,以使其适应特定的地理或文化区域 ...

  2. Eclipse 添加书签

    Eclipse 添加书签 关于书签 Eclipse 中可以在编辑器的任意一行添加书签. 您可以使用书签作为提示信息,或者使用书签快速定位到文件中的指定的行. 添加书签 如果你想设置书签,你只需要在垂直 ...

  3. Eclipse 内容辅助

    Eclipse 内容辅助 使用内容辅助 Eclipse中我们可以使用代码提示来加快开发速度,默认是输入"."后出现自动提示,用于类成员的自动提示. 设置自动提示的配置在:windo ...

  4. Spring入门第一例

    通过多天对基础语法的学习,早就向往一睹SPRING的芳容.今天按照ITEYE 唐的 教程,第一次运行Spring成功,步骤及注意事项如下: 一.基础环境 Jdk1.8, Eclipse4.71 .Sp ...

  5. windows下用py2exe打包脚本为可双击运行程序

    文件夹结构: ├── readme.txt ├── settings.py #程序参数 ├── settings.pyc ├── setup.py    #安装文件 ├── spider.ico   ...

  6. es6 async与await实战

    在使用js的时候,我们经常会遇到一个问题,就是我们需要等待请求返回再做下一步处理,之前的处理方式是通过ajax的success或者callback之类的方法,不过一层一层真的恶心,而且只是针对单个页面 ...

  7. MySQL没有远程连接权限设置

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; flush privileges ...

  8. TP数据删除

    [数据删除及执行原生sql语句] delete()  返回受影响的记录条数 $goods -> delete(30);   删除主键值等于30的记录信息 $goods -> delete( ...

  9. NOIP2011提高组(选择客栈)

    题目链接:http://codevs.cn/problem/1135/ 题目大意:中文题...就不解释了 题目思路:看了其他巨巨的blog写的,dp思路 #include <iostream&g ...

  10. VLC 媒体播放器

    VLC 媒体播放器 VLC 媒体播放器是一个便携式. 免费.开源. 跨平台的媒体播放器. VideoLAN 项目的流式媒体服务器.分为Windows Phone版本和Android版本. 下载地址: ...