通過(guò)源碼解析Laravel的依賴注入
前言
眾所周知,php的框架數(shù)不勝數(shù),近幾年,一個(gè)以優(yōu)雅著稱的框架,漸漸被國(guó)內(nèi)phper所知道,并且開(kāi)始使用,但是larave有一個(gè)很明顯的缺點(diǎn)就是,他的文檔內(nèi)容少的可憐。
本文將給大家詳細(xì)介紹關(guān)于Laravel依賴注入的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
在 Laravel 的控制器的構(gòu)造方法或者成員方法,都可以通過(guò)類型約束的方式使用依賴注入,如:
public function store(Request $request)
{
//TODO
}
這里 $request 參數(shù)就使用了類型約束,Request 是一個(gè)類:\Illuminate\Http\Request,表示參數(shù)必須是這個(gè)類或子類。
本文通過(guò)分析 Laravel 的源碼,看為什么方法中不需要傳入實(shí)例就可以直接使用 Request 呢?只是框架自動(dòng)幫我們實(shí)例化并傳參了。
1.路由定義
從源頭開(kāi)始看起,在路由定義文件中定義了這么一個(gè)路由:
Route::resource('/role', 'Admin\RoleController');
這是一個(gè)資源型的路由,Laravel 會(huì)自動(dòng)生成增刪改查的路由入口。

本文開(kāi)頭的 store 方法就是一個(gè)控制器的方法,圖中可見(jiàn)路由定義的 Action 也是:App\Http\Controllers\Admin\RoleController@store
路由方法解析
根據(jù)路由定義找到控制器和方法,執(zhí)行具體的方法在 dispatch 方法中實(shí)現(xiàn)。
(文件: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 方法,“顧名思義”是根據(jù)類的方法參數(shù)獲取依賴對(duì)象,然后再調(diào)用類的方法并把對(duì)象參數(shù)注入。
如果有多個(gè)依賴對(duì)象,也會(huì) foreach 依次解析出來(lái)作為參數(shù)注入。
獲取依賴對(duì)象示例的代碼:
protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
if (! method_exists($instance, $method)) {
return $parameters;
}
return $this->resolveMethodDependencies(
$parameters, new ReflectionMethod($instance, $method)
);
}
這里重點(diǎn)就是用到了 PHP 的反射,注意 RelectionMethod 方法,它獲取到類的方法參數(shù)列表,可以知道參數(shù)的類型約束,參數(shù)名稱等等。
這里的 $instance 參數(shù)就是 RoleController 控制器類,$method 參數(shù)就是方法名稱 strore.
2.獲取依賴對(duì)象的示例
從方法的參數(shù)中獲取了依賴對(duì)象的約束類型,就可以實(shí)例化這個(gè)依賴的對(duì)象。
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);
}
}
根據(jù)類名從容器中獲取對(duì)象,這個(gè)綁定對(duì)象實(shí)例的過(guò)程在服務(wù)提供者中先定義和了。
然后把實(shí)例化的對(duì)象傳入到 store 方法中,就可以使用依賴的對(duì)象了。
3.關(guān)于 PHP 反射
舉個(gè)使用 ReflectionMethod 的例子。
class Demo
{
private $request;
public function store(Request $request)
{
}
}
打印出 new ReflectionMethod(Demo::class, ‘store') 的內(nèi)容如圖:

可以得出這個(gè)方法的參數(shù)列表,參數(shù)的約束類型,如 typeHint,Illuminate\Http\Request.
根據(jù)類名可以從容器中獲取一開(kāi)始通過(guò)服務(wù)提供者綁定的實(shí)例。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
thinkphp ajaxfileupload實(shí)現(xiàn)異步上傳圖片的示例
本篇文章主要介紹了thinkphp ajaxfileupload實(shí)現(xiàn)異步上傳圖片的示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08
yii的入口文件index.php中為什么會(huì)有這兩句
這篇文章主要介紹了yii的入口文件index.php中為什么會(huì)有這兩句 的相關(guān)資料,需要的朋友可以參考下2016-08-08
Laravel框架定時(shí)任務(wù)2種實(shí)現(xiàn)方式示例
這篇文章主要介紹了Laravel框架定時(shí)任務(wù)2種實(shí)現(xiàn)方式,結(jié)合實(shí)例形式較為詳細(xì)的分析了Laravel框架定時(shí)任務(wù)相關(guān)實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下2018-12-12

