這篇文章主要給大家介紹了如何通過源碼解析Laravel的依賴注入的相關資料,文中通過範例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
前言
眾所周知,php的架構數不勝數,近幾年,一個以優雅著稱的架構,漸漸被國內phper所知道,並且開始使用,但是larave有一個很明顯的缺點就是,他的文檔內容少的可憐。
本文將給大家詳細介紹關於Laravel依賴注入的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
在 Laravel 的控制器的構造方法或者成員方法,都可以通過類型約束的方式使用依賴注入,如:
public function store(Request $request){ //TODO}
這裡 $request 參數就使用了類型約束,Request 是一個類:\Illuminate\Http\Request,表示參數必須是這個類或子類。
本文通過分析 Laravel 的源碼,看為什麼方法中不需要傳入執行個體就可以直接使用 Request 呢?只是架構自動幫我們執行個體化並傳參了。
1.路由定義
從源頭開始看起,在路由定義檔案中定義了這麼一個路由:
Route::resource('/role', 'Admin\RoleController');
這是一個資源型的路由,Laravel 會自動產生增刪改查的路由入口。
本文開頭的 store 方法就是一個控制器的方法,圖中可見路由定義的 Action 也是:App\Http\Controllers\Admin\RoleController@store
路由方法解析
根據路由定義找到控制器和方法,執行具體的方法在 dispatch 方法中實現。
(檔案:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)
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));}
首先 resolveClassMethodDependencies 方法,“顧名思義”是根據類的方法參數擷取依賴對象,然後再調用類的方法並把對象參數注入。
如果有多個依賴對象,也會 foreach 依次解析出來作為參數注入。
擷取依賴對象樣本的代碼:
protected function resolveClassMethodDependencies(array $parameters, $instance, $method){ if (! method_exists($instance, $method)) { return $parameters; } return $this->resolveMethodDependencies( $parameters, new ReflectionMethod($instance, $method) );}
這裡重點就是用到了 PHP 的反射,注意 RelectionMethod 方法,它擷取到類的方法參數列表,可以知道參數的類型約束,參數名稱等等。
這裡的 $instance 參數就是 RoleController 控制器類,$method 參數就是方法名稱 strore.
2.擷取依賴對象的樣本
從方法的參數中擷取了依賴對象的約束類型,就可以執行個體化這個依賴的對象。
protected function transformDependency(ReflectionParameter $parameter, $parameters){ $class = $parameter->getClass(); // If the parameter has a type-hinted class, we will check to see if it is already in // the list of parameters. If it is we will just skip it as it is probably a model // binding and we do not want to mess with those; otherwise, we resolve it here. if ($class && ! $this->alreadyInParameters($class->name, $parameters)) { return $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : $this->container->make($class->name); }}
根據類名從容器中擷取對象,這個綁定對象執行個體的過程在服務提供者中先定義和了。
然後把執行個體化的對象傳入到 store 方法中,就可以使用依賴的對象了。
3.關於 PHP 反射
舉個使用 ReflectionMethod 的例子。
class Demo{ private $request; public function store(Request $request) { }}
列印出 new ReflectionMethod(Demo::class, ‘store') 的內容
可以得出這個方法的參數列表,參數的約束類型,如 typeHint,Illuminate\Http\Request.
根據類名可以從容器中擷取一開始通過服務提供者綁定的執行個體。
總結
您可能感興趣的文章:
php資料結構之順序鏈表與鏈式線性表的樣本
基於php中echo用逗號和用點號的區別詳細講解
php實現統計二進位中1的個數演算法的樣本