首页 > 解决方案 > 从命令调度作业时无法实例化接口

问题描述

我在我的 Laravel 应用程序中编写了一个自定义工匠命令,它调度了一个 Job。该作业在其方法中具有服务依赖关系,该依赖关系handle()通过 Laravel 的 DI 机制解决。正常运行应用程序时会正确注入依赖项,但是,当我尝试php artisan my:command从终端运行时,会出现如下错误:

Symfony\Component\Debug\Exception\FatalThrowableError(代码:0):无法在 /Users/john/code/laravel-project/app/Providers/ABCServiceProvider.php:28 处实例化接口 App\Services\ABCInterface)

这是我的register()方法ABCServiceProvider(也请阅读评论):

public function register()
{
    $this->app->bind(ABCInterface::class, function ($app) {
        if ($app->environment(['testing', 'local'])) {

            // The following log statement is executed when the app runs normally.
            // But isn't executed when the artisan command is run from the console.
            \Log::debug('Instantiating FakeABCService'); 

            // The following class implements ABCInterface.
            return new FakeABCService;

        } else {

            // The following class implements ABCInterface.
            return new ABCService;
        }
    });
}

Job 被调度的handle()方法:

public function handle(ABCInterface $abcService)
{
    //
}

最后handle()是artisan命令类的方法:

/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $post = Post::first();

    if ($this->confirm("Are you sure?")) {
        MyJob::dispatch($post);
        $this->comment('Done!');
        return;
    }
}

另外,如果我将依赖项(类型提示)注入到handle()命令类的方法中,laravel 可以解决它。只是 Job 类的 handle() 方法无法解决依赖关系。

为什么在正常的应用流程中绑定的类被解析,但运行命令时却无法解析?我怎样才能解决这个问题?

标签: phplaravel

解决方案


由于 Job 的handle功能已在队列中解决,请尝试重新启动队列工作程序。

对代码进行更改后,您必须重新启动队列工作程序才能使更改在队列上生效。

请记住,队列工作者是长期存在的进程,并将启动的应用程序状态存储在内存中。因此,它们在启动后不会注意到您的代码库中的更改。因此,在您的部署过程中,请务必重新启动您的队列工作程序。

检查文档


推荐阅读