思考并回答以下问题:
前言
经过前面一系列中间件的工作,现在请求终于要达到了正确的控制器方法了。本篇文章主要讲Laravel如何调用控制器方法,并且为控制器方法依赖注入构建参数的过程。
路由控制器的调用
我们前面已经解析过中间件的搜集与排序、pipeline的原理,接下来就要进行路由的run运行函数:
1 |
|
路由的run函数主要负责路由控制器方法与路由闭包函数的运行:
1 | namespace Illuminate\Routing; |
路由的运行主要靠ControllerDispatcher这个类:
1 | class Route |
1 | namespace Illuminate\Routing; |
上面可以很清晰地看出,控制器的运行分为两步:解析函数参数、调用callAction
解析控制器方法参数
解析参数的功能主要由ControllerDispatcher类的RouteDependencyResolverTrait这一trait负责:
1 |
|
控制器方法函数参数构造难点在于,参数来源有三种:
- 路由参数赋值
- IoC容器自动注入
- 函数自带默认值
在IoC容器自动注入的时候,要保证路由的现有参数中没有相应的类,防止依赖注入覆盖路由绑定的参数:
1 | /** |
由IoC容器构造出的参数需要插入到原有的路由参数数组中:
1 | if (! is_null($instance)) |
当路由的参数数组与IoC容器构造的参数数量不足以覆盖控制器参数个数时,就要去判断控制器是否具有默认参数:
1 | elseif (! isset($values[$key - $instanceCount]) && $parameter->isDefaultValueAvailable()) |
调用控制器方法callAction
所有的控制器并非是直接调用相应方法的,而是通过callAction函数再分配,如果实在没有相应方法还会调用魔术方法__call() :
1 | namespace Illuminate\Routing; |
路由闭包函数的调用
路由闭包函数的调用与控制器方法一样,仍然需要依赖注入,参数构造:
1 |
|