Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel custom console command invoking constructor of all other custom commands

I have a set of console commands registered in app/Console/Kernel.php. My Kernel.php looks like,

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        Commands\ConsoleCommand1::class,
        Commands\ConsoleCommand2::class
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule $schedule
     *
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // Some code
    }
}

The structure of console command class looks like,

<?php namespace App\Console\Commands;

use Illuminate\Console\Command;
use Dependancy;

class ConsoleCommand1 extends Command
{
    protected $signature = ‘console_command_1’;
    protected $description = ‘This is the description’;
    private $dependancy;

    public function __construct(Dependancy $dependancy)
    {
        parent::__construct();
        $this->dependancy = $dependancy;
    }

    public function handle()
    {
        // Some code
    }
}

Now the problem is, whenever I execute any of the console commands from the list, the constructor of the other one also getting executed with the actually executed one.

For example, if I execute "php artisan console_command_1", the constructor of both "php artisan console_command_1" and "php artisan console_command_2" are getting executed and vice versa. I actually want only the constructor of 'actually executed artisan command' to be invoked.

Is this the way Laravel console command is designed or I am doing something wrong? Any help is highly appreciated.

like image 839
Tibin Paul Avatar asked Mar 28 '16 19:03

Tibin Paul


1 Answers

Yes, unfortunately this is the only way for Laravel to determine if an artisan command exists or not. Here are the two main things that happen when you run a command:

1. When you run an console command, the entry point is the artisan file located in the root of your project. That creates a kernel instance and calls the handle method on it passing along the received arguments (which are: the artisan command name and any additional arguments passed for it).

2. The kernel's handle method will run the artisan command and in order to do that it will need a console application instance (internally that is identified as Artisan), which will need to call resolveCommands to create a list of commands so it can check if the current command name is valid. That method will make a new instance of every command that is registered with the kernel (the ones you defined, as well as all the default ones loaded from the ArtisanServiceProvider).


So really, since in the Kernel you're registering the command via a class name reference:

Commands\ConsoleCommand1::class

And the command name is a protected property of that class:

protected $signature = ‘console_command_1’;

The only possible way to get a command name from a class is to create an instance of that class, thus all constructors are called for the entire command list to be created.

like image 185
Bogdan Avatar answered Oct 14 '22 08:10

Bogdan