将 Artisan 注入服务 class
Injecting Artisan into Service class
我正在尝试将 Artisan 注入到服务中,这样我就可以避免使用外观。
查看外观 class 参考,我可以看到我应该注入的 class 是:
Illuminate\Console\Application
所以我假设这样做:
<?php
namespace App\Service;
use Illuminate\Console\Application;
class DummyDataService
{
/**
* @var Application
*/
private $application;
public function __construct(
Application $application
) {
$this->application = $application;
}
public function insertDummyData()
{
$this->application->call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
}
}
...会起作用。但是,我收到以下错误:
BindingResolutionException in Container.php line 824:
Unresolvable dependency resolving [Parameter #2 [ <required> $version ]] in class Illuminate\Console\Application
如果我像这样在 facade 上调用方法,它会起作用:
Artisan::call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
到目前为止我无法弄清楚问题出在哪里。有没有人遇到过类似的问题?我尽量避免使用立面。
提前致谢。
如果您看一下 Illuminate\Console\Application
的构造函数,您会发现它需要一个 $version
参数并且不提供任何类型的默认值。因此,如果没有明确提供,它将因该依赖性而失败。老实说,这对我来说似乎是一个错误。如果查看其 Symphony 父项 class,您会发现它在其构造函数中提供了一个默认字符串 'UNKNOWN'
。如果您将 Illuminate\Console\Application
修改为具有相同的默认值,代码中的命令现在应该可以工作了。
这给您留下了两个选择。
- 只需为此实例使用 Artisan facade。对其余外观使用构造函数注入应该没问题,因为这会特别影响 Artisan 外观。
- 更改源代码中的构造函数以具有默认值。不太理想,因为每次更新 Laravel 时您的所有更改都将丢失,但这是一个选项。您也许可以制作某种服务提供商,将一个版本也注入所有
Illuminate\Console\Application
个实例,但我不确定。
老实说,我不确定将默认值添加到构造函数中是否会产生无法预料的后果,尽管我认为它们将是最小的,因为它必须在调用它的任何地方显式定义。我什至可以把它变成一个 PR,看看 Taylor 是否评论它或者只是合并它。
你应该注入 Illuminate\Contracts\Console\Kernel
而不是 Illuminate\Console\Application
来实现你想要的,所以你的 class 应该是这样的:
<?php
namespace App\Service;
use Illuminate\Contracts\Console\Kernel;
class DummyDataService
{
private $kernel;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
}
public function insertDummyData()
{
$this->kernel->call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
}
}
我正在尝试将 Artisan 注入到服务中,这样我就可以避免使用外观。 查看外观 class 参考,我可以看到我应该注入的 class 是:
Illuminate\Console\Application
所以我假设这样做:
<?php
namespace App\Service;
use Illuminate\Console\Application;
class DummyDataService
{
/**
* @var Application
*/
private $application;
public function __construct(
Application $application
) {
$this->application = $application;
}
public function insertDummyData()
{
$this->application->call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
}
}
...会起作用。但是,我收到以下错误:
BindingResolutionException in Container.php line 824:
Unresolvable dependency resolving [Parameter #2 [ <required> $version ]] in class Illuminate\Console\Application
如果我像这样在 facade 上调用方法,它会起作用:
Artisan::call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
到目前为止我无法弄清楚问题出在哪里。有没有人遇到过类似的问题?我尽量避免使用立面。
提前致谢。
如果您看一下 Illuminate\Console\Application
的构造函数,您会发现它需要一个 $version
参数并且不提供任何类型的默认值。因此,如果没有明确提供,它将因该依赖性而失败。老实说,这对我来说似乎是一个错误。如果查看其 Symphony 父项 class,您会发现它在其构造函数中提供了一个默认字符串 'UNKNOWN'
。如果您将 Illuminate\Console\Application
修改为具有相同的默认值,代码中的命令现在应该可以工作了。
这给您留下了两个选择。
- 只需为此实例使用 Artisan facade。对其余外观使用构造函数注入应该没问题,因为这会特别影响 Artisan 外观。
- 更改源代码中的构造函数以具有默认值。不太理想,因为每次更新 Laravel 时您的所有更改都将丢失,但这是一个选项。您也许可以制作某种服务提供商,将一个版本也注入所有
Illuminate\Console\Application
个实例,但我不确定。
老实说,我不确定将默认值添加到构造函数中是否会产生无法预料的后果,尽管我认为它们将是最小的,因为它必须在调用它的任何地方显式定义。我什至可以把它变成一个 PR,看看 Taylor 是否评论它或者只是合并它。
你应该注入 Illuminate\Contracts\Console\Kernel
而不是 Illuminate\Console\Application
来实现你想要的,所以你的 class 应该是这样的:
<?php
namespace App\Service;
use Illuminate\Contracts\Console\Kernel;
class DummyDataService
{
private $kernel;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
}
public function insertDummyData()
{
$this->kernel->call('db:seed', [
'--class' => 'DummyDataSeeder'
]);
}
}