Laravel 学习笔记之 Composer 自动加载
说明:本文主要以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 自动加载的更多相关文章
- [置顶] iOS学习笔记47——图片异步加载之EGOImageLoading
上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔 ...
- lumen之composer自动加载
composer作为PHP的包管理工具,让PHP可以使用命名空间, 载入对应的类文件,不用理会文件引入的路劲问题,代码可读性也大大提高 composer 自动加载 composer 自动加载的规则 v ...
- Flutter学习笔记(19)--加载本地图片
如需转载,请注明出处:Flutter学习笔记(19)--加载本地图片 上一篇博客正好用到了本地的图片,记录一下用法: 首先新建一个文件夹,这个文件夹要跟目录下 然后在pubspec.yaml里面声明出 ...
- composer 自动加载(php-amqplib)
最近要使用RabbitMQ 做消息队列,也是刚接触到.因为用的的TP框架,comoser又下载不下来,所以只能手动下载拓展包,做手动加载,在php-amqplib是我手动下载下来的拓展包,创建一个co ...
- composer 自动加载一 通过file加载
github地址 https://github.com/brady-wang/composer composer init 可以生成一个composer.json文件 { "name&quo ...
- Composer 自动加载(autoload)机制
自动加载的类型 总体来说 composer 提供了几种自动加载类型 classmap psr-0 psr-4 files 这几种自动加载都会用到,理论上来说,项目代码用 psr-4 自动加载, hel ...
- composer自动加载一个文件后必须执行命令composer dump-autoload
"autoload": { "classmap": [ "database" ], "psr-4": { "A ...
- composer 自动加载源码解析
一直在用 composer,最近想看一下具体的原理是什么,就仔细阅读了一下源码,一下是个人理解.在看该文章前最好了解一下 PSR-4 自动加载规范 引入类自动加载文件 # 加载类自动加载文件 requ ...
- composer 自动加载 通过classmap自动架子啊
https://github.com/brady-wang/composer github地址 composer加载自己写的类 放入一个目录下 更改composer.json "autolo ...
随机推荐
- Java基础09 类数据与类方法(转载)
我们一直是为了产生对象而定义类(class)的.对象是具有功能的实体,而类是对象的类型分类.这是面向对象的一个基本概念. static数据成员 有一些数据用于表述类的状态.比如Human类,我们可 ...
- 在eclipse中使用枚举简单类型enum
在JAVA中终于可以使用枚举类型了,就像在C或C++使用的简单枚举. 首先就在eclipse中试试它吧. 没想到,却报了错误.我装了jdk1.5(5.0),也在eclipse中设置了,怎么会不认识en ...
- (转载)Unity3D研究院之使用 C#合成解析XML与JSON(四十一)
XML与JSON在开发中非常重要, 其实核心就是处理字符串.一个是XML的字符串一个是JSON的字符串,尤其是在处理网络请求的时候,肯定是要用的.另外现在JSON非常的流行,我写了一个简单的例子融合了 ...
- 利用.Net中Process类调用netstat命令来判断计算端口的使用情况
利用.Net中Process类调用netstat命令来判断计算端口的使用情况: Process p = new Process();p.StartInfo = new ProcessStartInfo ...
- unintest基础1
import unittest class Testfunc(unittest.TestCase): def testfunc(self): print('testfunc1') def testfu ...
- jpofiler监控JVM
1.官方下载地址,选择自己想要的版本 https://www.ej-technologies.com/download/jprofiler/version_92 2.分为linux服务端.window ...
- 时间格式转换 json 转 datetime js c#
情景描述:使用C#在后台中传递时间到ajax中,因为是一个list<model>就直接用了Json 作为载体,但是在js中获得到的时间是var time='/Date(********** ...
- Online Judge(字符串-格式)
Online Judge Problem Description Ignatius is building an Online Judge, now he has worked out all the ...
- mysql 日期加减天数
MySQL 为日期增加一个时间间隔:date_add() now() //now函数为获取当前时间 select date_add(now(), interval 1 day); - 加1 ...
- outlook撤回已发送邮件
官方教程参考: https://support.office.com/zh-cn/article/%E5%8F%91%E9%80%81%E9%82%AE%E4%BB%B6%E5%90%8E%E6%92 ...