2014-11-22 165 views
6

什麼,我之前已經做是使用構造只有我的模型使用外牆爲Laravel的提供的類SessionAuthValidator等,例如注射。如果我通過構造並通過$this->..語法或注入每個類(我的或Laravel的),我是否應該使用構造函數注入我自己的類,並使用Facades來提供Laravel提供的任何東西,是否會成爲的好主意?Laravel:依賴注入vs Facades?

更具體地講,這裏是我的控制器通常是這樣的:

class MyController extends BaseController 
{ 
    public function __construct(User $user, Bookmark $bookmark) { 
     $this->user = $user; 
     $this->bookmark = $bookmark 
    } 

    public function foobar () { 
     $user_id = Input::get('bar'); 
     ... 
     Session::get('someInfo'); 
     ... 
     return Redirect::to('/'); 
    } 
    ... 
} 

我應該構建我的方法,如控制器一樣以下,而不是?

class MyController extends BaseController 
{ 
    public function __construct(User $user, Bookmark $bookmark, Input $input, Session $session, Redirect $redirect) { 
     $this->user = $user; 
     $this->bookmark = $bookmark 
     $this->input = $input; 
     $this->session = $session; 
     $this->redirect = $redirect; 
    } 

    public function foobar () { 
     $user_id = $this->input->get('bar'); 
     ... 
     $this->session->get('someInfo'); 
     ... 
     return $this->redirect->to('/'); 
    } 
    ... 
} 
+0

這個問題似乎是題外話,因爲它應該在程序員.stackexchange.com – 2014-11-22 18:26:08

+0

你知道嗎?爲什麼*你應該注入對象而不是使用Laravel的外觀? – 2014-11-22 18:44:31

+3

@FlorianMargaine,應該是*「立面」*。 – 2014-11-22 18:52:27

回答

1

Laravel現在支持對於那些路由相關的類的方法(不只是構造函數),如控制器和中間件相同的注射功能。

你可以防止不必要的注射僅注射到的依賴是獨一無二的,方法可能是在構造函數中留出更多的公共依賴:

class MyController extends BaseController 
{ 
    public function __construct(Input $input, Session $session, Redirect $redirect) { 
     $this->input = $input; 
     $this->session = $session; 
     $this->redirect = $redirect; 
    } 

    public function foobar (User $user, Bookmark $bookmark) { 
     $user_id = $this->input->get('bar'); 
     ... 
     $this->session->get('someInfo'); 
     ... 
     return $this->redirect->to('/'); 
    } 
    ... 
} 

至於你是否應該做這種方式,這是由你 - 強制所有依賴出現在方法定義中對我來說似乎更清晰,並且更容易進行單元測試。

0

注入某些類(例如Request)是優雅和有用的。在我看來,他們應該在需要它們的控制器方法中指定,因爲它們然後在邏輯上連接到方法實現。到目前爲止非常棒。

我發現兩個外牆是問題 - 應用程序和日誌。它們都不是邏輯上連接到控制器或其操作。應用程序和日誌不是任何情況下的輸入。由於應用程序和日誌是實用程序類,它們也與服務和存儲庫相關,如果在控制器中鍵入提示並將其作爲構造函數或方法參數傳遞給支持類,它就會變得非常討厭。

另一個問題是,App Facade沒有實現代理的Illuminate \ Contracts \ Auth \ Guard接口,所以我的IDE因警告而點亮,因爲無法進行靜態分析。

爲了保持關注的一致性和全面分離,我將因此在實例化構造函數或方法中實例化App和Log,具體取決於它們在類中的使用範圍。爲了讓我開心的IDE我創建了下面的類來給我一個正確類型的實例,無論我需要它:

<?php namespace App\Components; 

use Illuminate\Contracts\Auth\Guard; 
use Psr\Log\LoggerInterface; 

/** 
* Get the underlying object instances of facades from the container. 
*/ 
class AppGlobal 
{ 
    /** 
    * Returns the global logger instance. 
    * 
    * @return LoggerInterface 
    */ 
    public static function log() 
    { 
     return app('log'); 
    } 

    /** 
    * Returns the global auth instance, which internally proxies a guard. 
    * 
    * @return Guard 
    */ 
    public static function auth() 
    { 
     return app('auth'); 
    } 

} 
+0

這幾天人們走得更遠,使他們的軟件開心...... – 2017-02-26 23:48:54

0

如果你需要一個對象的屬性的智慧 - 把它作爲注射劑(如輸入,會話.. ),否則,如果你沒有在對象中存儲任何數據並且很喜歡使用類,那麼比使用外觀(比如Log :: ...,Redirect :: ...)要快。

0

Laravel已經取代了許多它的外立面與助手例如

use Auth; 

Auth::user() 

現在只是

auth()->user() 

這使得事情簡單,整潔的(也可以防止錯誤)

我會建議儘可能使用助手,如果沒有助手存在,請使用正面,因爲它比注入的實例更容易模擬。

+1

使用你描述的兩種方法在代碼/測試中創建了一個不必要的依賴,並依靠Laravel的魔法來解決靜態驗證::呼叫。其次使用全局函數調用再次創建依賴項。最好在構造函數中初始化依賴項並使用它。 – Nick 2017-11-14 21:38:47