Laravel自动注入和在构造函数主体中手动指定依赖项有什么区别?



我正在使用Laravel项目中的存储库模式。官方文档中并未真正解释过这种模式,除了该片段:

您可以在控制器的构造函数中键入由应用程序定义的存储库。存储库将自动解决并注入类。

这是我的代码,符合文档:

class CategoriesController extends Controller
{
    protected $repo;
    public function __construct(CategoriesRepository $repo)
    {
        $this->repo = $repo;
    }

我已经键入类别reposository,因此由服务容器自动加载。

但是,如果我直接创建一个类别Controller类的新实例(不使用服务容器(,我必须指定我也需要类别的新实例,例如:

$example = new CategoriesController(new CategoriesRepository());

现在,假设我编写以下代码。

class CategoriesController extends Controller
{
    protected $repo;
    public function __construct()
    {
        $this->repo = new CategoriesRepository();
    }

以这种方式,我不必通过服务容器加载类,也不必通过将类别的新实例作为参数来调用,因为它是在构造函数内部自动创建的。

那么,我的问题是:这是不好的做法吗?键入字体作为参数和在构造函数内部创建新实例之间有什么区别?

这是依赖注入的美:

复杂初始化

class MyController {
     public function __construct(A $a) { }
}
class A {
     public function __construct(B $b) { }
}
class B {
     public function __construct(C $c) { }
}
class C {
     public function __construct(D $d) { }
}
class D {
     public function __construct() { }
}

现在您可以要求Laravel为您创建该课程,例如:

$controller = make(MyController::class);

也可以做:

$controller = new MyController(new A(new B(new C(new D())))));

此外,您可以指定有关如何创建变量的更复杂的规则:

app()->bind(D::class, function ($app) {
       $d = new D();
       $d->setValueOfSomething($app->make(AnotherClass::class));
       return $d;
});

测试

这是依赖注入比手动创建事物的优点。另一个是单元测试:

    public function testSomeFunctionOfC() {
        $this->app->bind(D::class, function () {
               $dMock = $this->createMock(D::class);
        });
        $c = make(C::class);
    }

现在创建C时,D类将是模拟类,而是您可以根据规范确保工作。

最新更新