Laravel 一个请求的处理过程

0x0. 预备知识

在了解 Laravel 框架如何工作之前,需要了解一个非常重要的概念:Iversion of Control,即 IoC。搜索到一个对 IoC 非常简单易懂的描述:IoC 即将设计的类交给系统去控制,而不是在类内部进行控制,称为控制反转

具体可以参考如下链接,建议按照如下顺序进行阅读:

1.Laravel 官方文档中对 Service ContainerService Provider 的描述,按照目前的积累的经验进行初步理解

2.一个形象的 IoC 概述:http://stackoverflow.com/questions/18562752/understanding-ioc-containers-and-dependency-injection

3.通过简单的 PHP 代码描述 IoC:http://pimple.sensiolabs.org/

4.IoC 的用途、分类的详细叙述:http://www.martinfowler.com/articles/injection.html

最后再回过头来再参考一下 Service Container 和 Service Provider 文档,并且查看用户请求的生命周期概述:Request Lifecycle,基本上都可以非常清晰的理解。

0x1. 从茵蒂克丝开始

index

从 public/index.php 下包含的代码可以清晰地看到整个请求流程:先实例化 Application 对象,接着对 Request 进行处理,然后返回并发送一个 Response 对象,最后结束请求。

index.php

PS:autoload.php 可以略过,因为其具体实现由 Composer 提供,主要实现对类文件自动引用。

Application 对象由 bootstrap/app.php 返回,该文件先实例化一个 Application 对象,然后分别为 Http\Kernel、Console\Kernel 等分别绑定一个单实例:

app.php

0x2. Application 的实现

Application 的构造函数中主要调用了三个函数:registerBaseBindings, registerBaseServicePrivdersregisterCoreContainerAliases

Application.php

  1. registerBaseBindings 实现非常简单,设置当前实例到静态变量 $instance,并为当前实例设置 alias,最后将其绑定到 Container 接口。如果清楚了 IoC,那么下面的代码应该不难理解:

registerBaseBindings

  1. registerBaseServicePrivders 听其名知其义,基础的 Service Provider 设施从这里开始构建:

registerBaseServicePrivders

函数中实例化了 EventServiceProvider 和 RoutingServiceProvider,重点来看后者。RoutingServiceProvider 继承自 ServiceProvider,并根据要求至少重写一个 register 函数:

RoutingServiceProvider

继续跟进重要的函数 registerRouter。该函数实例化了我们熟悉的 Router 实例并保存到 Container 中:

registerRouter

进入到 Router 构造函数,除了获取传进来的参数,基本没多大动作。在 Router 类中,也可以看到熟悉的 get、post、group 等常用函数的实现:

Route.php

  1. registerCoreContainerAliases 函数为接口和类绑定 alias,比较简单。将 alias 绑定后,便可以通过 $app->make($alias) 来实例化一个类,同样参考 IoC 设计可以理解。

0x3. 追根溯源

回到 bootstrap/app.php,从上面可以了解到 Http\Kernel 接口其实是绑定到了 App\Http\Kernel.php 的实现:

$app->singleton(
    Illuminate\\Contracts\\Http\\Kernel::class,
    App\\Http\\Kernel::class
);

再退回 public/index.php,可以看到通过 Application 的 make 函数取回绑定到 Http\Kernel 接口的实力对象,其实该对象便是 App\Http\Kernel 的实例:

$kernel = $app->make(Illuminate\\Contracts\\Http\\Kernel::class);

Kernel.php 自然也是我们常去的地方,Middleware 也是在此声明的。Kernel 类继承自 Illuminate\Foundation\Http\Kernel 类,handle 函数便是在该类中实现的:

Illuminate\\Foundation\\Http\\Kernel

To be continue…