说明:本文主要以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. java string 首字母大小写方法

    String字符串需要进行首字母大小写改写,查询google,就是将首字母截取,转化大小写 + 首字母后面字符串 //首字母小写 public static String captureName(St ...

  2. python资源网站

    whl安装包资源网站:http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy

  3. Linux C 获取系统时间信息

    比如获取当前年份:               /* 获取当前系统时间 暂时不使用 ; ; time_t now; struct tm *timenow; time(&now); timeno ...

  4. ViewPager页面切换特效

    ViewPager页面切换特效如下效果 看效果: 效果1: 效果2: 下面就开始讲解如何实现这两个页面翻转效果 1.首先你得会ViewPager控件的使用(废话!现在还有人不会使用吗???!!) 2. ...

  5. cocos2D 虚拟摇杆Joystick功能实现

        @implementation InputLayer        - (id)init    {        if(self = [super init])        {        ...

  6. sql server数据库创建、删除,创建表,数据库的sql语句

    create database test on primary -- 默认就属于primary文件组,可省略(/*--数据文件的具体描述--*/ name='test', -- 主数据文件的逻辑名称 ...

  7. keras常用的网络层

    一.常用层 常用层对应于core模块,core内部定义了一系列常用的网络层,包括全连接.激活层等. 1.Dense层 Dense层:全连接层. keras.layers.core.Dense(outp ...

  8. proguard-project.txt和project.properties混淆代码

     [转]利用android proguard混淆代码 防止反编译,优化代码 网上虽然有很多相关博客,不过貌似都不是最新版的..于是百度+谷歌+github上的开源demo,终于成功的配置了androi ...

  9. IIPP迷你项目(二)"Guess the Number!"

    本来这个程序是早就编完了的,一直没时间发布博客.时至今日已时隔多天,也算是复习一下事件驱动型编程的过程吧. 1 事件驱动型编程 本质上这次的作业是披着猜数字皮的图形化界面编程,好在 simplegui ...

  10. CSS ,浮动,clear记录,和一些转载别处

    DIV+CSS clear both清除产生浮动 我们知道有时使用了css float浮动会产生css浮动,这个时候就需要清理清除浮动,我们就用clear样式属性即可实现. clear 属性规定元素的 ...