12

我之前一直在做的是只使用构造函数注入我的模型,为 Laravel 提供的类使用外观Session例如,等等Auth如果我通过构造注入每个类(无论是我的还是 Laravel 的)并通过语法使用它,或者我应该使用构造函数注入我自己的类并将 Facades 用于 Laravel 提供的任何东西,Validator这会是一个好主意吗?$this->..

更具体地说,这是我的控制器通常的样子:

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('/');
    }
    ...
}
4

4 回答 4

3

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 自动完成)。
  • 然后,只要依赖项是唯一的(大多数路由都不需要),请使用按方法注入与构造函数。
  • 因为让所有唯一的依赖项出现在方法定义中更容易进行单元测试(而且对我来说似乎更干净)。
于 2016-01-27T01:44:43.263 回答
1

注入某些类(例如 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');
    }

}
于 2017-02-04T10:34:06.270 回答
0

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

于 2017-02-27T00:10:21.030 回答
-1

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

use Auth;

Auth::user()

现在只是

auth()->user()

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

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

于 2017-11-13T19:56:14.337 回答