亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

Laravel控制器的解讀

2020-03-22 18:24:51
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了關于Laravel控制器的解讀,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

控制器

控制器能夠將相關的請求處理邏輯組成一個單獨的類, 通過前面的路由和中間件兩個章節我們多次強調Laravel應用的請求在進入應用后首現會通過Http Kernel里定義的基本中間件

protected $middleware = [ /Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode::html' target='_blank'>class, /Illuminate/Foundation/Http/Middleware/ValidatePostSize::class, /App/Http/Middleware/TrimStrings::class, /Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull::class, /App/Http/Middleware/TrustProxies::class,];

然后Http Kernel會通過dispatchToRoute將請求對象移交給路由對象進行處理,路由對象會收集路由上綁定的中間件然后還是像上面Http Kernel里一樣用一個Pipeline管道對象將請求傳送通過這些路由上綁定的這些中間鍵,到達目的地后會執行路由綁定的控制器方法然后把執行結果封裝成響應對象,響應對象一次通過后置中間件最后返回給客戶端。

下面是剛才說的這些步驟對應的核心代碼:

namespace Illuminate/Foundation/Http;class Kernel implements KernelContract protected function dispatchToRouter() return function ($request) { $this- app- instance( request , $request); return $this- router- dispatch($request);
namespace Illuminate/Routing;class Router implements RegistrarContract, BindingRegistrar public function dispatch(Request $request) $this- currentRequest = $request; return $this- dispatchToRoute($request); public function dispatchToRoute(Request $request) return $this- runRoute($request, $this- findRoute($request)); protected function runRoute(Request $request, Route $route) $request- setRouteResolver(function () use ($route) { return $route; $this- events- dispatch(new Events/RouteMatched($route, $request)); return $this- prepareResponse($request, $this- runRouteWithinStack($route, $request) protected function runRouteWithinStack(Route $route, Request $request) $shouldSkipMiddleware = $this- container- bound( middleware.disable ) $this- container- make( middleware.disable ) === true; //收集路由和控制器里應用的中間件 $middleware = $shouldSkipMiddleware ? [] : $this- gatherRouteMiddleware($route); return (new Pipeline($this- container)) - send($request) - through($middleware) - then(function ($request) use ($route) { return $this- prepareResponse( $request, $route- run()namespace Illuminate/Routing;class Route public function run() $this- container = $this- container ?: new Container; try { if ($this- isControllerAction()) { return $this- runController(); return $this- runCallable(); } catch (HttpResponseException $e) { return $e- getResponse();}

我們在前面的文章里已經詳細的解釋過Pipeline、中間件和路由的原理了,接下來就看看當請求最終找到了路由對應的控制器方法后Laravel是如何為控制器方法注入正確的參數并調用控制器方法的。

解析控制器和方法名

路由運行控制器方法的操作runController首現會解析出路由中對應的控制器名稱和方法名稱。我們在講路由那一章里說過路由對象的action屬性都是類似下面這樣的:

[ uses = App/Http/Controllers/SomeController@someAction , controller = App/Http/Controllers/SomeController@someAction , middleware = ...]
class Route protected function isControllerAction() return is_string($this- action[ uses  protected function runController() return (new ControllerDispatcher($this- container))- dispatch( $this, $this- getController(), $this- getControllerMethod() public function getController() if (! $this- controller) { $class = $this- parseControllerCallback()[0]; $this- controller = $this- container- make(ltrim($class, //  return $this- controller; protected function getControllerMethod() return $this- parseControllerCallback()[1]; protected function parseControllerCallback() return Str::parseCallback($this- action[ uses class Str //解析路由里綁定的控制器方法字符串,返回控制器和方法名稱字符串構成的數組 public static function parseCallback($callback, $default = null) return static::contains($callback, @ ) ? explode( @ , $callback, 2) : [$callback, $default];}

所以路由通過parseCallback方法將uses配置項里的控制器字符串解析成數組返回, 數組第一項為控制器名稱、第二項為方法名稱。在拿到控制器和方法的名稱字符串后,路由對象將自身、控制器和方法名傳遞給了Illuminate/Routing/ControllerDispatcher類,由ControllerDispatcher來完成最終的控制器方法的調用。下面我們詳細看看ControllerDispatcher是怎么來調用控制器方法的。

class ControllerDispatcher use RouteDependencyResolverTrait; public function dispatch(Route $route, $controller, $method) $parameters = $this- resolveClassMethodDependencies( $route- parametersWithoutNulls(), $controller, $method if (method_exists($controller, callAction )) { return $controller- callAction($method, $parameters); return $controller- {$method}(...array_values($parameters));}

上面可以很清晰地看出,ControllerDispatcher里控制器的運行分為兩步:解決method的參數依賴resolveClassMethodDependencies、調用控制器方法。

解決method參數依賴

解決方法的參數依賴通過RouteDependencyResolverTrait這一trait負責:

trait RouteDependencyResolverTrait protected function resolveClassMethodDependencies(array $parameters, $instance, $method) if (! method_exists($instance, $method)) { return $parameters;
return $this- resolveMethodDependencies( $parameters, new ReflectionMethod($instance, $method) //參數為路由參數數組$parameters(可為空array)和控制器方法的反射對象 public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector) $instanceCount = 0; $values = array_values($parameters); foreach ($reflector- getParameters() as $key = $parameter) { $instance = $this- transformDependency( $parameter, $parameters if (! is_null($instance)) { $instanceCount++; $this- spliceIntoParameters($parameters, $key, $instance); } elseif (! isset($values[$key - $instanceCount]) $parameter- isDefaultValueAvailable()) { $this- spliceIntoParameters($parameters, $key, $parameter- getDefaultValue()); return $parameters;}

在解決方法的參數依賴時會應用到PHP反射的ReflectionMethod類來對控制器方法進行方向工程, 通過反射對象獲取到參數后會判斷現有參數的類型提示(type hint)是否是一個類對象參數,如果是類對象參數并且在現有參數中沒有相同類的對象那么就會通過服務容器來make出類對象。

 protected function transformDependency(ReflectionParameter $parameter, $parameters) $class = $parameter- getClass(); if ($class ! $this- alreadyInParameters($class- name, $parameters)) { return $parameter- isDefaultValueAvailable() ? $parameter- getDefaultValue() : $this- container- make($class- name); protected function alreadyInParameters($class, array $parameters) return ! is_null(Arr::first($parameters, function ($value) use ($class) { return $value instanceof $class; })); }

解析出類對象后需要將類對象插入到參數列表中去

 protected function spliceIntoParameters(array $parameters, $offset, $value) array_splice( $parameters, $offset, 0, [$value] }

我們之前講服務容器時,里面講的服務解析解決是類構造方法的參數依賴,而這里resolveClassMethodDependencies里解決的是具體某個方法的參數依賴,它Laravel對method dependency injection概念的實現。

當路由的參數數組與服務容器構造的類對象數量之和不足以覆蓋控制器方法參數個數時,就要去判斷該參數是否具有默認參數,也就是會執行resolveMethodDependencies方法foreach塊里的else if分支將參數的默認參數插入到方法的參數列表$parameters中去。

} elseif (! isset($values[$key - $instanceCount])  $parameter- isDefaultValueAvailable()) { $this- spliceIntoParameters($parameters, $key, $parameter- getDefaultValue());}
調用控制器方法

解決完method的參數依賴后就該調用方法了,這個很簡單, 如果控制器有callAction方法就會調用callAction方法,否則的話就直接調用方法。

 public function dispatch(Route $route, $controller, $method) $parameters = $this- resolveClassMethodDependencies( $route- parametersWithoutNulls(), $controller, $method if (method_exists($controller, callAction )) { return $controller- callAction($method, $parameters); return $controller- {$method}(...array_values($parameters)); }

執行完拿到結果后,按照上面runRouteWithinStack里的邏輯,結果會被轉換成響應對象。然后響應對象會依次經過之前應用過的所有中間件的后置操作,最后返回給客戶端。

以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP !

相關推薦:

Laravel事件系統的解讀

以上就是Laravel控制器的解讀的詳細內容,PHP教程

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲片av在线| 国产精品网址在线| 国产精品免费视频久久久| 欧美性生交xxxxx久久久| 日韩欧美国产免费播放| 欧美专区国产专区| 欧美成人剧情片在线观看| 在线观看日韩欧美| 久久精品这里热有精品| 日韩欧美国产一区二区| 久久久黄色av| 国产成+人+综合+亚洲欧洲| 欧美野外猛男的大粗鳮| 欧美久久精品一级黑人c片| 精品久久久精品| 性色av一区二区咪爱| 亚洲国产成人一区| 亚洲国内精品视频| 91国内产香蕉| 欧洲亚洲免费视频| 亚洲国产精品网站| 97久久精品人搡人人玩| 精品高清美女精品国产区| 欧美极品少妇xxxxⅹ裸体艺术| 精品国产999| 色综合久久88| 91视频8mav| 亚洲欧美制服第一页| 亚洲一区国产精品| 欧美一级大片在线观看| 久久久久久久久久久成人| 2025国产精品视频| 91精品国产成人www| 亚洲综合中文字幕在线观看| 欧美第一黄网免费网站| 日韩亚洲欧美成人| 精品福利在线视频| 91精品在线看| 九九热99久久久国产盗摄| 色一情一乱一区二区| 亚洲一区二区三| 国产精品精品一区二区三区午夜版| 国模精品视频一区二区| 2019亚洲男人天堂| 国产主播精品在线| 国产福利视频一区| 成人av在线亚洲| 久久在线观看视频| 大伊人狠狠躁夜夜躁av一区| 91精品久久久久久久久久久| 日本精品在线视频| 国产精品美女主播在线观看纯欲| 日韩欧亚中文在线| 欧美性视频网站| 欧美性黄网官网| 亚洲性av在线| 97在线视频免费播放| zzjj国产精品一区二区| 中国china体内裑精亚洲片| 欧美成人网在线| 成人h猎奇视频网站| 精品亚洲国产视频| 精品成人久久av| 欧美在线视频免费播放| 久久国产精品久久久久久久久久| 亚洲欧洲自拍偷拍| 欧美野外猛男的大粗鳮| 欧美最猛性xxxx| 欧美日韩国产成人高清视频| 国内精品小视频| 亚洲欧洲激情在线| 久久精品中文字幕免费mv| 中文字幕亚洲综合久久筱田步美| 久久久亚洲天堂| 欧美性猛交xxxx黑人| 久久精品一本久久99精品| 久久精品国产成人| 亚洲欧美另类人妖| 日韩中文字幕av| 91精品国产色综合| 91精品国产综合久久男男| 最近2019年手机中文字幕| 国产亚洲精品va在线观看| 久久影院免费观看| 亚洲天堂免费观看| 91九色国产在线| 97视频在线观看播放| 亚洲一区二区在线播放| 久久久久久伊人| 综合136福利视频在线| 亚洲天天在线日亚洲洲精| 亚洲高清一区二| 日本欧美中文字幕| 亚洲自拍在线观看| 91av在线国产| 亚洲剧情一区二区| 成人黄色av免费在线观看| 日韩av在线免费播放| 欧美精品做受xxx性少妇| 亚洲国产日韩欧美在线99| 国产日韩精品综合网站| 亚洲视频777| 国产精品久久久久不卡| 国产精品a久久久久久| 色老头一区二区三区在线观看| 国产一区二区三区在线观看视频| 日韩精品一区二区视频| 午夜剧场成人观在线视频免费观看| 中文字幕免费国产精品| 日本精品视频在线| 在线观看中文字幕亚洲| 国产97在线|亚洲| 欧美性色xo影院| 国产成人自拍视频在线观看| 日韩亚洲第一页| 欧美精品一本久久男人的天堂| 91免费在线视频| 欧美性猛交xxxx免费看漫画| 色噜噜狠狠狠综合曰曰曰| 日韩视频免费大全中文字幕| 91精品在线观看视频| 亚洲色图综合久久| 成人国产亚洲精品a区天堂华泰| 亚洲欧美在线第一页| 菠萝蜜影院一区二区免费| 欧美专区第一页| 热门国产精品亚洲第一区在线| 国产精品一区二区三区成人| 亚洲乱码av中文一区二区| 亚洲欧美资源在线| 国产亚洲精品一区二区| 亚洲综合在线小说| 国产精品入口夜色视频大尺度| 国产精品福利久久久| 奇门遁甲1982国语版免费观看高清| 日韩av黄色在线观看| 日本高清视频精品| 亚洲精品久久久一区二区三区| 亚洲第一精品夜夜躁人人爽| 欧美午夜久久久| 中文字幕亚洲欧美日韩高清| 两个人的视频www国产精品| 亚洲一区二区三区四区视频| 91精品久久久久久久久久久| 欧美中在线观看| 亚洲人成电影网站色www| 欧美亚洲另类制服自拍| 久久久亚洲成人| 日韩电影免费观看在线观看| 久久久久久久影院| 久久精品中文字幕免费mv| 一个人看的www久久| 亚洲一区二区三区香蕉| 国产精品白嫩初高中害羞小美女| 亚洲天堂av网| 亚洲欧洲偷拍精品| 日韩国产精品亚洲а∨天堂免| 久久久久国产精品一区| 97免费在线视频| 国产视频观看一区| 国产综合久久久久久| 在线免费观看羞羞视频一区二区| 欧美性生活大片免费观看网址| 992tv成人免费视频|