Laravel 自定义控制台命令调用所有其他自定义命令的构造函数

Laravel custom console command invoking constructor of all other custom commands

我在 app/Console/Kernel.php 中注册了一组控制台命令。我的 Kernel.php 看起来像,

<?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
    }
}

控制台命令class的结构如下所示,

<?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
    }
}

现在的问题是,每当我执行列表中的任何控制台命令时,另一个命令的构造函数也会与实际执行的命令一起执行。

例如,如果我执行 "php artisan console_command_1","php artisan console_command_1" 和 "php artisan console_command_2" 的构造函数都会被执行,反之亦然。我实际上只想调用 'actually executed artisan command' 的构造函数。

这是 Laravel 控制台命令的设计方式还是我做错了什么?非常感谢任何帮助。

是的,不幸的是,这是 Laravel 确定 artisan 命令是否存在的唯一方法。以下是当您 运行 命令时发生的两件主要事情:

1. 当您 运行 控制台命令时,入口点是位于项目根目录中的 artisan 文件。这会创建一个内核实例并 calls the handle method on it 传递接收到的参数(它们是:artisan 命令名称和为其传递的任何其他参数)。

2.内核的handle方法会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).


确实如此,因为在 Kernel 中您通过 class 名称引用注册命令:

Commands\ConsoleCommand1::class

并且命令名称是 class:

的受保护 属性
protected $signature = ‘console_command_1’;

从 class 获取命令名称的唯一可能方法是创建该 class 的实例,因此会调用所有构造函数来创建整个命令列表。