laravel后台控制器参数解析学习
在配置laravel路由的时候,路由的url可能存在参数,它是如何被解析到控制器的呢。
在Illuminate\Routing\Router类中的 dispath(Request $request) 方法,这个方法实际上就是路由匹配后执行的操作,即调用与路由匹配的某个控制器下的某个方法。它返回的是 $this->dispatchRoute($request) ,进入到这个方法。
进入runRoute方法。
返回值使用了管道,用于穿过中间件,最终在then中执行闭包返回响应,点击 $route->run() 。
进入到 $this->runController() 中。
$this->controllerDispatcher();//这里返回的是Illuminate\Routing\ControllerDispatcher对象 ,进入这个类的dispatch方法中
这里找到了解析参数的方法, $this->resolveClassMethodDependencies($route->parametersWithoutNulls(),$controller,$method); 进入这个方法
如果这个方法不存在,直接返回参数,$instance即为解析的控制器类名,进入到下面的方法
开始解决依赖了,$parameters 即为url的请求参数,根据反射解析出该控制器需要的参数(只解析控制器所需的类,然后插入,其它Class参数不解析,url参数按控制器参数的排序来并非路由中定义的参数名)。控制器方法所需的参数也有可能是个对象,这样的参数是无法根据url参数解析的,而是通过内部的容器动态的创建这个对象,继续解析其它的参数,解析成功实例数加一($instance),并把解析的对应参数插入到对应位置,如果参数类型不是类,则不解析按默认的 $parameters 排序来,即url 的参数排序。
如果设置的路由是
Route::get('/debug/args/{id}/{name}', 'Admin\DebugController@args');
请求的url是 http://localhost/debug/args/2/DennisRitche
而控制器的参数顺序是
public function args(DubugFormRequest $request,$name,$id){ }
那么根据框架的逻辑,解析到这些参数前,请求参数为
[ 0=>$request //DebugFormRequest的对象 'id'=>"2", 'name'=>"DennisRitche" ]
但是由于反射出来的参数顺序与请求参数并不一样,在解析完所有实例之后参数是这样的,之后回到之前的方法中 dispatch(Route $route,$controller,$method)//Illuminate\Routing\ControllerDispatcher对象中的方法 最终执行 $controller->{$method}(...array_values($parameters)); ,整个控制器的执行调用完成。而按照之前的解析顺序,原本的id成了name,name成了id。