【问题标题】:Laravel : Dependency injection vs Facades?Laravel:依赖注入与门面?
【发布时间】:2014-11-22 18:10:19
【问题描述】:

我之前所做的是使用构造函数只注入我的模型为 Laravel 提供的类使用 Facades,即SessionAuthValidator 等,例如。 如果我通过构造注入每个类(我的或 Laravel 的)并通过 $this->.. 语法使用它,或者 我应该使用构造函数注入我自己的类,这会是一个好主意吗? strong> 并为 Laravel 提供的任何东西使用 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('/');
    }
    ...
}

【问题讨论】:

  • 这个问题似乎离题了,因为它应该在programmers.stackexchange.com上
  • 你知道为什么你应该注入对象而不是使用 Laravel 的门面吗?
  • @FlorianMargaine ,应该是 "facades"
  • 我认为这样做取决于您对 IOC 绑定的看法。如果该对象将在所有/大多数控制器方法中使用,则传递给构造是有意义的。示例可能是:元(标题、描述等)。然后,您将在其他地方添加您的绑定如果另一方面您只是在整个应用程序中稀疏地使用一个类,那么外观更有意义。示例:验证器、会话、重定向。 (在控制器方法的上下文中)

标签: php laravel laravel-facade


【解决方案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('/');
    }
    ...
}

结论

至于你是否应该这样做,这取决于你,但考虑:

  • 首先,使用 Dependency-Injection 与 Facade(也启用 IDE 自动完成)。
  • 然后,只要依赖项是唯一的(大多数路由都不需要),请使用按方法注入与构造函数。
  • 因为让所有唯一的依赖项出现在方法定义中更容易进行单元测试(而且对我来说似乎更干净)。

【讨论】:

    【解决方案2】:

    注入某些类是优雅而有用的,例如Request。在我看来,它们应该在需要它们的控制器方法中指定,因为它们随后在逻辑上连接到方法实现。到目前为止很棒。

    我发现有两个外观存在问题 - 应用程序和日志。两者都没有逻辑连接到控制器或其操作。 App 和 Log 在任何上下文中都不是输入。由于 App 和 Log 是实用程序类,它们也与服务和存储库相关,如果您在控制器中键入提示它们,然后将它们作为构造函数或方法参数传递给您的支持类,它会变得非常讨厌。

    另一个问题是 App 外观没有实现它代理的 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');
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      如果您需要一个具有属性的对象 - 将其作为注入(例如 Input、Session...)放入,否则,如果您没有在对象中存储任何数据并且非常乐意使用类,则不要使用外观(例如 Log::...、Redirect::...)。

      【讨论】:

        【解决方案4】:

        Laravel 已经用助手替换了它的许多外观

        use Auth;
        

        Auth::user()
        

        现在只是

        auth()->user()
        

        这让事情变得更简单和整洁(也可以防止错误)

        我建议在可能的情况下使用助手,如果不存在助手,请使用外观,因为它比注入实例更容易模拟。

        【讨论】:

        • 使用您描述的两种方法都会在代码/测试中创建不必要的依赖关系,并依赖 Laravel 魔法来解决静态 Auth:: 调用。其次使用全局函数调用再次创建依赖项。最好在构造函数中初始化依赖并使用它。
        猜你喜欢
        • 2015-05-31
        • 2022-01-16
        • 2016-07-19
        • 2023-03-23
        • 2014-02-02
        • 1970-01-01
        • 2012-10-02
        • 2018-02-20
        • 2015-03-02
        相关资源
        最近更新 更多