Laravel 执行流程(二)之 Container 类(上)

备注:纯手打的学习笔记,如有错误之处请指正,谢谢。希望大家学的开心!

定位

接上一章的内容,我们继续。

  • 来到 bootstrap/app.php

发现了一段英文注释,翻译过来为:

/ *
| --------------------------------------------------------------------------
|创建应用程序
| --------------------------------------------------------------------------
|
|我们首先要做的是创建一个新的 laravel 应用实例
|作为“胶水”用于 laravel 的所有组件,并
|为系统结合各种零件的 IOC 容器。
|
* /

换句话说,把这个对象实例作为一个可依靠稳固的地基,来存放各种“建筑物(组件)”,So 地基= IOC 容器? 好复杂有木有,不管它了,读代码去吧,读代码就像聊天,得用心倾听别人的心声。

紧接着 new 了一个对象。
new Illuminate\Foundation\Application() 构造函数做了什么?对了,Application 类还传入了当前 laravel 根目录的地址这样一个参数。如 “D:\webSite\Laravel” 。
命名空间 Illuminate 的具体文件路径位于
Vendor/laravel/framework/src/Illuminate。

然后根据命名空间的顺序找到目录 Foundation,再找到文件 Application.php 打开即可。
打开文件,我又醉了,先是定义一个命名空间,接着各种 use,往下看,到这里:

class Application extends Container implements ApplicationContract, HttpKernelInterface

继承 Container 类,对应上面的use:use Illuminate\Container\Container; 并且要实现2个接口 ApplicationContract,HttpKernelInterface,
咱们先看看这个 Container 类到底是什么。
怎么找具体文件上面已经说过了,下面就直接略过,直接打开 Container.php。

Container 类

打开文件,第一反应又要去补知识了。

The ArrayAccess interface 数据访问接口,PHP5的一个新接口,接口提供访问对象数组。

需要实现四个方法:

  • abstract public boolean offsetExists ( mixed $offset )
  • abstract public mixed offsetGet ( mixed $offset )
  • abstract public void offsetSet ( mixed $offset , mixed $value )
  • abstract public void offsetUnset ( mixed $offset )

先不用懂这4个方法是什么意思,看看 Container 类怎么实现的就懂了。

file

当外部使用 isset() 函数时触发此方法,而方法内部则也是使用一个 isset 来判断返回一个 bool 值。这个 bindings 先不管,我们主要知道这个方法做了什么事情。

file

当外部尝试获取 $key 的时候,如 echo ,print_r,var_dump,赋值等。
就会触发此方法,而方法内部也是直接一个 reutrn,简单!

file

当外部尝试赋值的时候,则触发此方法。
此方法内部先进行一个 instanceof 判断 如果 value 参数不是一个闭包,则将 ·$value· 封装成一个闭包,而闭包函数的内部直接一个 return ,下面的 bind 不知道先不管。

file

当外部尝试使用 unset 函数的时候触发此方法,
图上的方法内部是一个 unset 函数,那些变量看不懂,先不管。

这就是 ArrayAccess,一个类实现它的4个方法,在不同操作时触发4个方法,知道这些就够了,具体调用的示例这里我没有举出来,PHP 官网有,请自行翻阅,锻炼下动手能力。

好吧继续往下看,又要开始补知识了,我去。

  • use ReflectionClass
  • use ReflectionMethod
  • use ReflectionFunction
  • use ReflectionParameter

这几个类又是什么鬼?崩溃!
Reflection =反射。 为了好理解些,我们就比喻成手术医生吧。
上面4个类都分别实现了 Refletor 这个接口,大家可以去看看这里:

http://php.net/manual/zh/class.reflector.p...

然后这几个反射类里面有一些方法,就像动手术有不同的手法,要针对不同的病人实施不同的手法,而病人则需要给上面4个的构造函数传入一个参数(病人姓名),我们先来看看姓名为 “index” 的病人的就医过程。

具体代码如下:

namespace index;
use ReflectionClass;
use ReflectionMethod;
use ReflectionFunction;
use ReflectionParameter;

class index //病人姓名index
{ 
    public function a(){}

}
function b($b,$c,$d)
{ 
}

/* ReflectionClass 示例
//找到医生ReflectionClass,医生问了姓名叫啥? 额... index\index
//那你有什么问题呢? 我想查查我会被人克隆吗?
//嗯,这个问题问的好。 我用我的isFinal手法给你查查看
//结果dump出一个false,你会被复制,因为你少了Final。
//就医结束
$a = new ReflectionClass('index\index'); 
var_dump($a->isFinal()); //false
*/

就是这么简单,其他高超的手法请自行PHP官网翻阅。

  • ReflectionMethod 针对类方法。
  • ReflectionFunction 针对普通函数
  • ReflectionParameter 针对函数的参数

具体代码演示如下:

/* ReflectionMethod 示例
$a = new ReflectionMethod('index\index','a');
var_dump($a->isAbstract()); //false
*/

/* ReflectionParameter 示例
$a = new ReflectionParameter('index\b',2);
var_dump($a->getName()); //string(1) "d"
*/

/* ReflectionFunction 示例
$a = new ReflectionFunction('index\b');
var_dump($a->getParameters());
array(3) {
  [0]=>
  &object(ReflectionParameter)#2 (1) {
    ["name"]=>
    string(1) "b"
  }
  [1]=>
  &object(ReflectionParameter)#3 (1) {
    ["name"]=>
    string(1) "c"
  }
  [2]=>
  &object(ReflectionParameter)#4 (1) {
    ["name"]=>
    string(1) "d"
  }
}
*/

好了,相信聪明的你应该知道反射了,继续看代码呗。

Use InvalidArgumentException 这个比较简单 ,请自行百度。

然后看到 Container 类还实现这个接口 ContainerContract。

对应 use Illuminate\Contracts\Container\Container as ContainerContract;

提示:Contracts 翻译“合同、契约”。

接口里面的方法有兴趣可自行查看,我们主要看 Container 的实现这些方法的细节。

最后我们简述下 Contracts 作为本章结束语:
我的理解是一系列组件服务的接口集合,好处?松耦合,有多松?怎么松?我也是菜鸟不要问我,以后咱们读代码自然会了解他的好处。

请关注 Laravel 执行流程(二)Container 类(下)

未完待续。。。。。

下一章:Laravel 执行流程(三)之 探索 Application 构造函数

本帖已被设为精华帖!
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 6
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!