Is dependency injection of a custom class in a command
possible?
I'm trying this:
<?php
namespace vendor\package\Commands;
use Illuminate\Console\Command;
use vendor\package\Models\Log;
use vendor\package\Updates\UpdateStatistics;
class UpdatePublishmentStats extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'vendorname:updatePublishmentStats';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Updates Twitter followers & Facebook page likes';
/**
* Contact implementation
* @var vendor\package\Update\UpdateStatistics
*/
protected $stats;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(
Log $log,
UpdateStatistics $stats
) {
parent::__construct();
$this->log = $log;
$this->stats = $stats;
}
But when I try to do this:
public function handle()
{
$this->stats->updateFbStats();
}
I suddenly get Segmentation fault: 11
When I delete the use vendor\package\Updates\UpdateStatistics;
part, I don't get that error.
So what am I doing wrong here? Is it not possible to use dependency injection in a command?
In Laravel, dependency injection is the process of injecting class dependencies into a class through a constructor or setter method. This allows your code to look clean and run faster. Dependency injection involves the use of a Laravel service container, a container that is used to manage class dependencies.
The constructor is a method that is called whenever a new instance of a (PHP) class is instantiated. This is object oriented programming 101.
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means this: class dependencies are "injected" into the class via the constructor or, in some cases, "setter" methods.
Dependency injection is a procedure where one object supplies the dependencies of another object. Dependency Injection is a software design approach that allows avoiding hard-coding dependencies and makes it possible to change the dependencies both at runtime and compile time.
You can inject any service in the handle
method:
Note that we are able to inject any dependencies we need into the command's
handle
method.
Source: https://laravel.com/docs/5.8/artisan#command-structure
According to the Command Structure section of 5.2 documentation (https://laravel.com/docs/5.2/artisan#writing-commands):
"Note that we are able to inject any dependencies we need into the command's constructor. The Laravel service container will automatically inject all dependencies type-hinted in the constructor."
So I think you're good there, as far as the capability being present and available.
As for getting it to work, for me the segfault points to something wrong with the UpdateStats class, how it's referenced in the service container, or how its being resolved from the service container.
I don't have a definitive answer, but what I would do is try another class and see if I could localize the issue to this particular class, or if the problem happens with others, and then try and debug from there.
Also, if you just can't get that to work, the app()
function will resolve items from the service container when you want (although looking through the 5.2 docs I don't see it anymore, so it may be deprecated - I do see $this->app->make()
however).
This may work for you if nothing else does:
public function __construct(
Log $log,
) {
parent::__construct();
$this->log = $log;
$this->stats = app(UpdateStatistics::class);
}
My guess is, however, that you will get a segfault with this as well, as it should try resolving the same class the same way. If you do, then at least the error is a little clearer, and unrelated to auto-injecting feature.
Hope that at least helps a little.
Update on the app()
function
So the app()
function does not appear to be documented, but I have 5.2 installed right now and the helpers.php file in Illuminate/Foundation definitely has the function:
if (! function_exists('app')) {
/**
* Get the available container instance.
*
* @param string $make
* @param array $parameters
* @return mixed|\Illuminate\Foundation\Application
*/
function app($make = null, $parameters = [])
{
if (is_null($make)) {
return Container::getInstance();
}
return Container::getInstance()->make($make, $parameters);
}
}
Unfortunately the API documentation doesn't include any of the helper functions, but the current master, 5.2, and 5.3 versions of the file on Github all have the function:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With