Laravel:依赖注入与Facades?

时间:2014-11-22 18:10:19

标签: php laravel laravel-facade

我之前做过的是使用构造函数仅注入我的模型,使用Facade为Laravel提供的类,即Session,{{例如,1}},Auth等。如果我通过构造注入每个类(无论是我的还是Laravel的)并通过Validator语法或使用构造函数注入我自己的类,这将是一个好主意吗? 并使用外墙来完成Laravel提供的任何事情?

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

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

4 个答案:

答案 0 :(得分: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('/');
    }
    ...
}

至于你是否应该这样做,那取决于你 - 强迫所有依赖项出现在方法定义中对我来说似乎更清晰,更容易进行单元测试。

答案 1 :(得分:0)

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

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

另一个问题是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');
    }

}

答案 2 :(得分:0)

如果您需要一个对象机智属性 - 将其作为注入(例如输入,会话...),否则,如果您不在对象中存储任何数据并且使用类非常满意,那么请使用外观(例如Log :: ...,Redirect :: ...)。

答案 3 :(得分:0)

Laravel用帮手取代了许多门面,例如

use Auth;

Auth::user()

现在只是

auth()->user()

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

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