laravel源码详解
来源:互联网 发布:先导爱知在第六季出现 编辑:程序博客网 时间:2024/05/31 06:22
安装,和创建项目,都是通过Composer,简单,略过。
Entry && Kernel
网站入口文件,${Laravel-project}/public/index.PHP:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
生成Request,处理Request(Http\Kernel::handle()
),生成Response,发送Resonse。常规的Web处理流程。
注意 Illuminate\Contracts\Http\Kernel
只是一个Interface:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
可见入口文件中的代码,$kernel = $app->make
是关键,后面都是调用Kerenl接口的实例对象方法(特别是Kernel::handle()
)。
可是 $app 是谁创建的呢?是什么类型呢?
Bootstrap && Application
入口文件的第一行代码:
- 1
- 1
引导我们去查看 bootstrap/app.php 源码,代码不多,都拿过来看看吧:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
第一行创建,最后一行返回。现在我们知道啦,$app
是Illuminate\Foundation\Application
类型的对象。(因为require_once
,$app
是一个单实例对象。中间几行代码后面可能有用,此处暂时忽略。)
自然,$kernel = $app->make()
也就是调用Applicaton::make()
了,代码拿来看一下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
然而还是不清楚它具体返回哪个类型。
对照前面bootstrap的代码:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
我们推论得出:$kernel = $app->make()
的真实类型是App\Http\Kernel
(同时实现了接口Illuminate\Contracts\Http\Kernel
)。
这个推论很容易被证实,此处省略细节($app->singleton->bind->alias->make())。
更加具体的创建Kernel对象的细节十分琐碎,我们也一并忽略,有兴趣的可以去看父类方法Illuminate\Container\Container::make()/build()
的代码。
现在我们初步总结一下:先new出Application类型对象
附加:$app是被直接new出来的(new Illuminate\Foundation\Application
),其构造函数做了一些重要的初始化工作,整理代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Kernel::handle() && Request=>Response
下一步我想知道 $response = $kernel->handle($request)
内部具体做了什么工作,是怎么处理Request并生成Response的。
前面我们已经分析过了,$kernel的真实类型是App\Http\Kernel
,也实现了接口Illuminate\Contracts\Http\Kernel
。
拿来App\Http\Kernel::handle()
的源代码看看,咦,没有此方法。
看其父类同名方法Illuminate\Foundation\Http\Kernel::handle()
代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
上面代码中我感兴趣的只有sendRequestThroughRouter($request)
这个调用,进去看一下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
上面代码中最后一行是我们关注的重点,它把Request送进一个新创建的流水线(Pipeline),
供各个中间件(Middleware)处理,然后再派发给路由器(Router)。下文将展开分析。
Pipeline && Middleware && Router
流水线,中间件,路由器。
Pipleline
流水线Illuminate\Pipeline\Pipeline
实现了接口Illuminate\Contracts\Pipeline\Pipeline
。
其主要接口方法有send
,through
,via
,then
。其中send
设置Request对象,through
设置中间件数组,via
设置方法名(默认为”handle”),then
最终运行此并执行闭包参数(then
的代码极其复杂,各种闭包嵌套,把我搞糊涂了,有兴趣的朋友可以看一下)。
简单推断来说,其工作内容是:依次调用各中间件的handle
方法。特别的,如果某个中间件是闭包,以闭包的形式调用之。
Middleware
中间件Illuminate\Contracts\Routing\Middleware
是一个很简单的接口:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
其文档也极其简陋,看不出太多有价值的信息。第二个参数什么意思,返回值什么意思,鬼才能看出来。可能需要从其他地方入手研究中间件。
Router
将请求派发给Router的调用流程:$kernel->handle($request)
=> $kernel->sendRequestThroughRouter
=> $kernel->dispatchToRouter()
=> $kernel->router->dispatch($request)
。
其中$kernel->router
是创建$kernel时通过构造函数传入的Router对象。
有必要先看一下Router是怎样创建出来的。调用流程:$app = new Applicaton
(__construct) => $app->register(new RoutingServiceProvider($app))
=> RoutingServiceProvider->register()->registerRouter()
。
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
Unresolved
流水线怎么调用中间件,怎么派发给路由器,路由器又是怎么工作的呢?这中间有很多细节还没搞明白。
流水线那里,代码很绕,暂时无法理解。中间件那里,文档太简陋,暂时无法理解。路由器运行原理那里,暂时还没有去看代码。
目前就是这个样子,此文到此为止吧。我想我需要去看一下Laravel 5.1的基础文档,然后再回头去读源码,可能效果会更好。
补记
Bootstrap
我之前在分析Kernel::handle()
时,忽略了一个地方,Kernel::sendRequestThroughRouter()
内部调用了Kernel::bootstrap()
方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Kernel::bootstrap()
内部又调用了Applicaton::bootstrapWith()
:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
Applicaton::bootstrapWith()
的参数是Kernel::bootstrappers()
,其初始值为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
以其中RegisterProviders
为例,其bootstrap()
方法调用了$app->registerConfiguredProviders()
:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
其中$this->config['app.providers']
的值来自于文件config/app.php
:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
大家都看到了,Kernel和Application互相交叉调用,Bootstrap过程又穿插在Request处理过程中间。暂时看不出清晰的思路。
- laravel源码详解
- laravel经典源码
- Laravel 源码解读
- laravel中间件源码分析
- Laravel源码(流程)解析
- Laravel 源码解读
- Laravel 包引入详解
- laravel数据库迁移详解
- Laravel控制器详解
- Laravel框架详解
- Laravel框架详解 CURD
- Laravel框架详解 CURD
- laravel 路由 详解
- laravel框架详解
- Laravel控制器详解
- laravel envoy详解
- Laravel 5.1 源码阅读笔记
- 194 laravel 源码分析-1
- Mybatis Generator最完整配置详解
- 缓存更新的套路
- js中变量前两个叹号(!!)作用
- Linux、socket笔记
- Spring常用的注解
- laravel源码详解
- Neo4j 数据导出为 CSV 格式
- 剑指offer:把字符串转换成整数
- hdu 6153 A Secret(KMP)
- HDU 4523 湫秋系列故事——安排座位【组合dp】【好题】【思维题】
- 每天一个linux命令(2):cd命令
- MySQL架构设计谈:从开发规范、选型、拆分到减压
- 【stm32f103】USART TX发送实现(寄存器版)
- HDU-6156 Palindrome Function(数位DP)