2014-11-22 121 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