php - Laravel 自动注入(inject)和在构造函数体中手动指定依赖有什么区别?

标签 php laravel inversion-of-control

我在我的 Laravel 项目中使用了 Repository 模式。官方文档中并未真正解释此模式,except for this snippet :

You may type-hint a repository defined by your application in a controller's constructor. The repository will automatically be resolved and injected into the class.

根据文档,这是我的代码:

class CategoriesController extends Controller
{
    protected $repo;

    public function __construct(CategoriesRepository $repo)
    {
        $this->repo = $repo;
    }

我已经对 CategoriesRepository 进行了类型提示,因此服务容器会自动加载它。

但是,如果我直接创建 CategoriesController 类的新实例(不使用服务容器),我必须指定我也需要 CategoriesRepository 的新实例,如下所示:

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

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

class CategoriesController extends Controller
{
    protected $repo;

    public function __construct()
    {
        $this->repo = new CategoriesRepository();
    }

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

所以,我的问题是:这会是不好的做法吗? 将类型提示作为参数与在构造函数中创建新实例有什么区别?

最佳答案

这是依赖注入(inject)的美妙之处:

复杂的初始化

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;
});

测试

这是依赖注入(inject)相对于手动创建事物的优势之一。另一个是单元测试:

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

现在,当您创建 C 时,类 D 将成为模拟类,您可以确保它按照您的规范工作。

关于php - Laravel 自动注入(inject)和在构造函数体中手动指定依赖有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44413926/

相关文章:

php - 如何在网站上显示两个文本之间的差异(例如 diff 或 WinMerge 但在 JS 中)

php - 基于多个 ID 和第一个 hasMany 图像表检索 Laravel 模型结果

javascript - 在哪里存储 JWT token Laravel 5.6 应用程序?

inversion-of-control - 哪些 IOC 容器可与 Windows Azure 配合使用

php - 在 Symfony2 中直接使用库而不是包

php - 在从 php 网页调用的 bash 脚本中克隆 git

php - Drupal 7 表单在迁移后不起作用。提交后表单字段变为空

mysql - 数据库sql内容上的多个图像

c# - Ioc 中繁忙的构造函数——它们是代码的味道吗?

asp.net-mvc - Nopcommerce 新表服务注册错误