I wrote a custom artisan command in my Laravel app, which dispatches a Job. The job has a service dependency in it's handle()
method which is resolved via Laravel's DI mechanism. The dependency is injected properly when running the app normally, however, when I try to run php artisan my:command
from terminal, I get an error like this:
Symfony\Component\Debug\Exception\FatalThrowableError(code: 0): Cannot instantiate interface App\Services\ABCInterface at /Users/john/code/laravel-project/app/Providers/ABCServiceProvider.php:28)
Here is my the register()
method of ABCServiceProvider
(Please read the comments also):
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;
}
});
}
The handle()
method of the Job being dispatched:
public function handle(ABCInterface $abcService)
{
//
}
Finally, the handle()
method of the artisan command class:
/**
* 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;
}
}
Also, If I inject the dependency (type-hint) to The handle()
method of the command class, laravel can resolve it. It's just the Job class' handle() method that's failing to resolve the dependency.
Why is it that the bound class is being resolved in normal application flow, but failing to be resolved when running the command? How can I fix this?