【问题标题】:Laravel dependency injection in a command method命令方法中的 Laravel 依赖注入
【发布时间】:2021-02-20 08:55:01
【问题描述】:

如果有人发现我的问题的标题很常见,我很抱歉,但事实是我已经尝试了几个小时来获得预期的结果,但我没有成功。

碰巧我正在为 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 接口时,它会返回具体的BaseCommand

    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 类注入ExampleCommand 类的handle 方法,但事实并非如此。如果您能给我任何帮助,我将不胜感激。

【问题讨论】:

  • 你的BaseCommand真的实现了那个接口吗?
  • 嗨@lagbox,目前不是BaseCommand 仅从Illuminate\Console\Command 类扩展我应该在BaseCommand 类中实现MyInterface 接口吗?

标签: laravel laravel-5 laravel-artisan


【解决方案1】:

您的BaseCommand 必须实现您为该handle 方法键入提示的接口。依赖注入发生在方法被调用之前,所以容器解析了你的绑定(因为它试图将BaseCommand 的实例传递给方法调用,handle)但是绑定没有返回实现该契约的东西,所以 PHP不允许为该参数传递该参数,因为它与签名中参数的类型不匹配(不实现合同)。

简而言之:如果您要将具体绑定到抽象,请确保具体是您要绑定的类型。

【讨论】:

  • 你完全正确,这回答了我的问题。非常感谢。
猜你喜欢
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 2014-04-19
  • 1970-01-01
  • 2022-01-16
  • 2016-07-19
相关资源
最近更新 更多