Laravel 命令方法中的依赖注入
Laravel dependency injection in a command method
如果有人发现我的问题的标题很常见,我很抱歉,但事实是我已经尝试了几个小时来获得预期的结果,但我没有成功。
碰巧,我正在为 Laravel 开发一个小包,但我无法在将包含该包的命令中的方法中执行依赖项注入。
在我的包的目录结构中,我有 ServiceProvider
<?php
namespace Author\Package;
use Author\Package\Commands\BaseCommand;
use Author\Package\Contracts\MyInterface;
use Illuminate\Support\ServiceProvider;
class PackageServiceProvider extends ServiceProvider
{
/**
* The commands to be registered.
*
* @var array
*/
protected $commands = [
\Author\Package\Commands\ExampleCommand::class
];
/**
* Register services.
*
* @return void
*/
public function register()
{
if (! $this->app->configurationIsCached()) {
$this->mergeConfigFrom(__DIR__ . '/../config/package.php', 'package');
}
$this->app->bind(MyInterface::class, BaseCommand::class);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__ . '/../config/package.php' => config_path('package.php')
], 'package-config');
$this->configureCommands();
}
}
/**
* Register the package's custom Artisan commands.
*
* @return void
*/
public function configureCommands()
{
$this->commands($this->commands);
}
}
正如您从 register
方法中看到的,我正在创建一个 binding
用于当它调用 MyInterface
接口时,它 returns 具体 BaseCommand
class
public function register()
{
...
$this->app->bind(MyInterface::class, BaseCommand::class);
}
ExampleCommand
文件的结构如下:
<?php
namespace Author\Package\Commands;
use Author\Package\Contracts\MyInterface;
use Illuminate\Console\Command;
class ExampleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'my:command';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command Description';
/**
* Execute the console command.
*
* @return void
*/
public function handle(MyInterface $interface)
{
// TODO
}
}
但是当我运行命令时,我得到以下错误:
TypeError
Argument 1 passed to Author\Package\Commands\ExampleCommand::handle() must be an instance of Author\Package\Contracts\MyInterface, instance of Author\Package\Commands\BaseCommand given
我想知道为什么依赖注入不起作用,本质上它应该将具体的 BaseCommand
class 注入到 ExampleCommand
[=38= 的 handle
方法中],但事实并非如此。如果您能给我任何帮助,我将不胜感激。
您的 BaseCommand
必须实现您为该 handle
方法提供类型提示的接口。依赖注入发生在调用方法之前,因此容器解析了您的绑定(因为它试图将 BaseCommand
的实例传递给方法调用,handle
)但绑定不会 return 实现该合同的东西,因此 PHP 不允许为该参数传递该参数,因为它与签名中的参数类型不匹配(不实现合同)。
简而言之:如果您要将具体绑定到抽象,请确保具体是您要绑定到的类型。
如果有人发现我的问题的标题很常见,我很抱歉,但事实是我已经尝试了几个小时来获得预期的结果,但我没有成功。
碰巧,我正在为 Laravel 开发一个小包,但我无法在将包含该包的命令中的方法中执行依赖项注入。
在我的包的目录结构中,我有 ServiceProvider
<?php
namespace Author\Package;
use Author\Package\Commands\BaseCommand;
use Author\Package\Contracts\MyInterface;
use Illuminate\Support\ServiceProvider;
class PackageServiceProvider extends ServiceProvider
{
/**
* The commands to be registered.
*
* @var array
*/
protected $commands = [
\Author\Package\Commands\ExampleCommand::class
];
/**
* Register services.
*
* @return void
*/
public function register()
{
if (! $this->app->configurationIsCached()) {
$this->mergeConfigFrom(__DIR__ . '/../config/package.php', 'package');
}
$this->app->bind(MyInterface::class, BaseCommand::class);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__ . '/../config/package.php' => config_path('package.php')
], 'package-config');
$this->configureCommands();
}
}
/**
* Register the package's custom Artisan commands.
*
* @return void
*/
public function configureCommands()
{
$this->commands($this->commands);
}
}
正如您从 register
方法中看到的,我正在创建一个 binding
用于当它调用 MyInterface
接口时,它 returns 具体 BaseCommand
class
public function register()
{
...
$this->app->bind(MyInterface::class, BaseCommand::class);
}
ExampleCommand
文件的结构如下:
<?php
namespace Author\Package\Commands;
use Author\Package\Contracts\MyInterface;
use Illuminate\Console\Command;
class ExampleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'my:command';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command Description';
/**
* Execute the console command.
*
* @return void
*/
public function handle(MyInterface $interface)
{
// TODO
}
}
但是当我运行命令时,我得到以下错误:
TypeError
Argument 1 passed to Author\Package\Commands\ExampleCommand::handle() must be an instance of Author\Package\Contracts\MyInterface, instance of Author\Package\Commands\BaseCommand given
我想知道为什么依赖注入不起作用,本质上它应该将具体的 BaseCommand
class 注入到 ExampleCommand
[=38= 的 handle
方法中],但事实并非如此。如果您能给我任何帮助,我将不胜感激。
您的 BaseCommand
必须实现您为该 handle
方法提供类型提示的接口。依赖注入发生在调用方法之前,因此容器解析了您的绑定(因为它试图将 BaseCommand
的实例传递给方法调用,handle
)但绑定不会 return 实现该合同的东西,因此 PHP 不允许为该参数传递该参数,因为它与签名中的参数类型不匹配(不实现合同)。
简而言之:如果您要将具体绑定到抽象,请确保具体是您要绑定到的类型。