2017-03-15 200 views
3

我試圖在Laravel中執行依賴注入以使我的控制器和模型儘可能地保持苗條。目標是讓存儲庫處理提取歸因於某些模型的數據。Laravel控制器依賴注入

爲此我試圖從文檔here和流行Laravel樣板here

效仿的榜樣,但我不明白的地方的$user的來源。

所以在看樣板,我們有兩個文件:

ProfileControllerhere

摘錄如下:

use App\Repositories\Frontend\Access\User\UserRepository; 
/** 
* Class ProfileController. 
*/ 
class ProfileController extends Controller 
{ 
    /** 
    * @var UserRepository 
    */ 
    protected $user; 
    /** 
    * ProfileController constructor. 
    * 
    * @param UserRepository $user 
    */ 
    public function __construct(UserRepository $user) 
    { 
     $this->user = $user; 
    } 

這看起來很像在文檔中提到的依賴注入,這是:

class UserController extends Controller { 

    /** 
     * The user repository instance. 
     */ 
     protected $users; 

     /** 
     * Create a new controller instance. 
     * 
     * @param UserRepository $users 
     * @return void 
     */ 
     public function __construct(UserRepository $users) 
     { 
      $this->users = $users; 
     } 

我的問題是我不明白$user是從哪裏來的。

UserRepository沒有$ user定義爲類本身的參數。沒有在代碼中的任何地方Auth::user(),所以我很困惑用戶實例來自哪裏。

+0

'$ user'只是變量的名稱。它也可以是'$ biggieSmalls'或其他任何東西。該變量只保存「UserRepository」的一個實例。 – devk

+0

Laravel的DIC創建它,因爲控制器需要一個。 – bassxzero

+0

@devk該實例分配給該變量的位置在哪裏?我知道它可以被命名爲任何東西,但我不明白它在哪裏分配。它不是在類型暗示是嗎? –

回答

5

在Laravel依賴注入處理由Container。我正在簡化,但您可以將容器看作對象的來源。如果存在單身人士,則將其存儲在容器中。否則容器知道如何爲你實例化對象。每當Laravel調用方法(如在控制器中)或爲您實例化一個對象時,它將檢查構造函數並查找類型提示的依賴項。如果它看到一個依賴關係,它知道如何檢索或創建它將會這樣做並將它傳遞給你。

所以當Laravel實例化控制器,它看起來在構造

public function __construct(UserRepository $user) 
{ 
    $this->user = $user; 
} 

容器使用類型提示看,它需要一個UserRepository所以它將實例爲你一個新的。它也遞歸地做到這一點。因此,當它創建一個新的UserRepository時,它會查看該構造函數,並發現它需要RoleRepository,因此它也會實例化該構造函數。

TLDR:服務容器檢查您的依賴關係,並將爲您實例化它們。

+0

好吧,這是有道理的。然後看起來Repository會根據傳遞的電子郵件判斷哪個用戶是基於它的,不明白爲什麼它不會使用'Auth :: user();'但是我想這是我的下一個任務!謝謝:) –

+0

如何注入需要使用setters配置的類。是否有與zend框架2.4相同的工廠模式?謝謝 – xiarnousx

+0

@xiarnousx我對Zend Framework並不熟悉,所以我不確定它是如何比較的,但是你可以通過[綁定到容器]定義一個對象應該如何構造(https://laravel.com/docs/ 5.5/container#binding-basics)然後,Laravel將使用該閉包在您請求注入時創建該對象。 – jfadich

2

歡迎來到Laravel的可疑魔法。這些依賴注入的基本思想是,根據您如何定義路由控制器,Laravel可以執行一些URL自動分析,標識這些URL中的ID以及獲取對象的數據庫。

我的問題是我不明白$用戶來自哪裏。

您應該讀取docs on the service container。你也可以得到你的路由定義如何轉化爲參數載貨網址,使用此命令一個更好的主意:

php artisan route:list 

在我的項目之一,這導致這樣的輸出:

+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+ 
| Domain | Method | URI      | Name    | Action           | Middleware | 
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+ 
|  | GET|HEAD |/      |     | Closure           | web   | 
|  | GET|HEAD | api/user     |     | Closure           | api,auth:api | 
|  | GET|HEAD | categories     | categories.index | App\Http\Controllers\[email protected] | web   | 
|  | POST  | categories     | categories.store | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/create   | categories.create | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/{category}  | categories.show | App\Http\Controllers\[email protected] | web   | 
|  | PUT|PATCH | categories/{category}  | categories.update | App\Http\Controllers\[email protected] | web   | 
|  | DELETE | categories/{category}  | categories.destroy | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/{category}/edit | categories.edit | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products     | products.index  | App\Http\Controllers\[email protected] | web   | 
|  | POST  | products     | products.store  | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/create   | products.create | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/{product}   | products.show  | App\Http\Controllers\[email protected]  | web   | 
|  | PUT|PATCH | products/{product}   | products.update | App\Http\Controllers\[email protected] | web   | 
|  | DELETE | products/{product}   | products.destroy | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/{product}/edit | products.edit  | App\Http\Controllers\[email protected]  | web   | 
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+ 

和所有這些路由及其uris和參數僅由幾個非常簡單的路由定義生成。這是我的路線文件:

$ cat routes/web.php 
<?php 

Route::get('/', function() { 
    return view('master'); 
}); 

Route::resource('products', 'ProductController'); 
Route::resource('categories', 'CategoryController'); 

如果你看的URI的路由輸出列表的上方,你會看到和{}產品中的URI命名爲喜歡{}類參數。這些對應於Laravel標識的URI中的id/keys。 Laravel是「聰明的」,足以查看我的控制器文件,查看各種函數中的類型提示,並檢測到我的函數正期望注入依賴。

例如,分類控制器的方法是這樣的:

public function show(Tree $category) 
{ 
    var_dump($category); 
} 

,因爲我,我想類型樹的對象類型提示我的控制器似乎有點不尋常,但Laravel是足夠聰明地認識到我確實需要一個類型樹模型,所以它解析出url並找到它的id並自動獲取我的db表中的記錄,其ID與我的{category}片段匹配網址並注入到我的功能。

請注意,我試圖命名輸入參數$ tree而不是$ category時,我輸入了had some trouble。那另一個線程可能有助於回答你的問題。

底線是,Laravel做了很多「魔術」,希望能夠讓你從繁瑣的手動定義自己的代碼和查詢來檢索你想要的對象。