如何在Laravel Artisan命令中正确注入依赖项?

13

基本上,我想从 Laravel 命令中调用存储库 Repository.php 上的一个方法。

Example\Storage\Repository.php
Example\Storage\RepositoryInerface.php
Example\Storage\RepositoryServiceProvider.php

我希望在命令构造函数中设置接口,并将其设置为受保护的变量。

在服务提供者中,我将接口绑定到仓库类。

现在,在 start/artisan.php 中,我只是写入:

Artisan::add(new ExampleCommand(new Repository());

我能在这里使用一个接口吗?正确的方法是什么?我感到困惑。

提前感谢。

编辑:为了澄清,目前只有这种方式可行,但我不想在注册artisan命令时硬编码具体类。

2个回答

17
你可以使用IoC容器的自动依赖注入功能:

您可以使用IoC容器的自动依赖注入功能:

Artisan::add(App::make('\Example\Commands\ExampleCommand'));
// or
Artisan::resolve('\Example\Commands\ExampleCommand');

如果ExampleCommand的构造函数接受一个具体类作为其参数,那么它将自动注入。如果它依赖于接口,则需要告诉IoC容器在请求给定接口时使用特定的具体类。

具体类(为简洁起见忽略命名空间):

class ExampleCommand ... {
    public function __construct(Repository $repo) {
    }
}

Artisan::resolve('ExampleCommand');

接口(为简洁起见忽略命名空间):

class ExampleCommand ... {
    public function __construct(RepositoryInterface $repo) {
    }
}

App::instance('RepositoryInterface', new Repository);
Artisan::resolve('ExampleCommand');

Command构造函数接受Repository接口,命令本身不在IoC中,只有Repository需要注入到位于默认目录中的命令中。 - Ren
我不明白的是,我需要改变什么才能将Artisan::add(new ExampleCommand(new Repository());更改为Artisan::add(new ExampleCommand(new RepositoryInterface()); - Ren
您不需要在IoC容器中使用命令 - IoC容器非常聪明,如果它得到一个尚未在容器中的“类名”,它会尝试实例化它它构造函数的依赖项。尝试我的代码并查看,只需确保使用FQCNs即可。 - alexrussell
真是太神奇了。尝试了 Artisan::add(App::make('\Example\Commands\ExampleCommand'));,结果正如预期一样。我在哪里可以阅读更多相关信息呢?您能详细说明一下吗? :) - Ren
在文档中已经有比较详细的解释了(http://laravel.com/docs/ioc#automatic-resolution)。我认为自动解析的便利副作用就是您可以使用`App::make()`创建任何类。重点在于,当IoC容器需要进行自动解析时,它只知道构造函数的参数,从中推断出提示的类,然后确定如何创建实例以传递进去。所以,不必为此创建受保护的方法,Taylor 将其作为 make() 方法的一部分,因此任何代码都可以使用它,而不仅仅是 IoC 容器。 - alexrussell
为了更新我上面评论中的文档链接,新的“永久链接”是https://laravel.com/docs/4.2/ioc#automatic-resolution。 - alexrussell

0

您可以在构造函数中使用interface来类型提示所依赖的对象,但是您必须在IoC容器中绑定具体类到接口,例如以下方式,这样它才能正常工作。

App::bind('Example\Storage\RepositoryInerface', 'Example\Storage\Repository');

请在文档中了解更多信息。


是的,我已经在ServiceProvider中这样做了,并且在Command构造函数中它可以正常工作,但是我如何在这里传递接口 Artisan::add(new ExampleCommand(new Repository()); - Ren
你不需要传递它,IoC容器会自动注入依赖项。 - The Alpha
那么我必须在这里使用具体类吗?那绑定又如何帮助我呢?如果我使用接口实现另一个类,我将需要更改绑定并在此处进行更改。我错过了什么?请查看我对其他答案的评论。 - Ren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接