I was wondering if you could help me with the problem that I found a few hours ago and I have not been able to solve it. I happen to be trying to develop a small package in Laravel
. This package will contain several commands
, but for now I need those commands
to inherit some methods and properties from a parent class
. I have defined the following structure in my project:
package
├── composer.json
└── src
├── Commands
│ └── ACommand.php
│ └── BCommand.php
├── Package.php
└── PackageServiceProvider.php
I register the commands inside the PackageServiceProvider
as follows:
<?php
namespace Author\Package;
use Illuminate\Support\ServiceProvider;
class PackageServiceProvider extends ServiceProvider
{
/**
* The commands to be registered.
*
* @var array
*/
protected $commands = [
\Author\Package\Commands\ACommand::class,
\Author\Package\Commands\BCommand::class,
];
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->commands($this->commands);
}
}
Let's take the ACommand
command as an example, it contains the following very basic structure to be brief:
<?php
namespace Author\Package\Commands;
use Author\Package\Package;
use Illuminate\Console\Command;
class ACommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:name';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle(Package $package)
{
return 0;
}
}
As you can see, in the handle()
method I do dependency injection
to the Package
class. This is the content of the Package
class:
<?php
namespace Author\Package;
use Illuminate\Console\Concerns\InteractsWithIO;
class Package
{
use InteractsWithIO;
public function __construct()
{
$this->info("Hello World!");
}
}
when I run the command:
php artisan command:name
I get the following error in the terminal:
Call to a member function writeln() on null
What other kinds of things have I tried?
- Create a
base command
andextend
the other commands to thatclass
, it would be as follows:
package
├── composer.json
└── src
├── Commands
│ └── ACommand.php
│ └── BCommand.php
│ └── BaseCommand.php
└── PackageServiceProvider.php
Let's take the ACommand
command as an example here:
<?php
namespace Author\Package\Commands;
use Illuminate\Console\Command;
class ACommand extends BaseCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:name';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
...
the content of BaseCommand
in this case I have left it like this:
<?php
namespace Author\Package\Commands;
use Author\Package\Package;
use Illuminate\Console\Command;
abstract class BaseCommand extends Command
{
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->info("Hello World!");
}
}
and I get the same error as a result:
Call to a member function writeln() on null
- Also setting the
BaseCommand
class asconcrete
and not asabstract
I get the same error.
Basically for now what I need is to do almost all my logic from the __construct()
method in a parent class .. and leave the result in a property
. Then from a child class
, access that property
, since all my commands are going to use that property .. but each one of them is going to do something different with that property.. But it happens that I have not been able to execute statements as I would in a simple command
, even when the parent class
extends from the class: Illuminate\Console\Command
.
As you can see in the example I am basically trying to display a message in the terminal called from the parent class
when the command
is executed. But I have not succeeded.
I have not done Dependency Injection
from the __construct()
method for the following reason:
All artisan command constructors are fired when running any artisan command...what?
Change artisan console to only fire constructors for the command being called
As you can see, when Dependency Injection
is done in the __construct()
method of a command
, it is executed in any other command
, that is why the documentation advises to do this Dependency Injection
in the handle()
method.
I have also read something here, but it has not served me much:
Laravel command cannot call $this->info() in child class
Please if someone expert on the subject could help me. Basically I am trying here, to call methods of the child class (ACommand
) from the parent class (Package
). I would appreciate any help in advance.