Skip to content

Artisan 控制台

介绍

Artisan 是 Laravel 附带的命令行界面的名称。它提供了许多有用的命令供您在开发应用程序时使用。它由强大的 Symfony Console 组件驱动。要查看所有可用的 Artisan 命令列表,您可以使用 list 命令:

php
php artisan list

每个命令还包括一个“帮助”屏幕,显示并描述命令的可用参数和选项。要查看帮助屏幕,只需在命令名称前加上 help

php
php artisan help migrate

编写命令

除了 Artisan 提供的命令之外,您还可以为您的应用程序构建自己的自定义命令。您可以将自定义命令存储在 app/Console/Commands 目录中;不过,只要您的命令可以根据 composer.json 设置自动加载,您可以自由选择自己的存储位置。

要创建新命令,您可以使用 make:console Artisan 命令,它将生成一个命令模板以帮助您入门:

php
php artisan make:console SendEmails

上面的命令将在 app/Console/Commands/SendEmails.php 生成一个类。在创建命令时,可以使用 --command 选项来分配终端命令名称:

php
php artisan make:console SendEmails --command=emails:send

命令结构

生成命令后,您应填写类的 signaturedescription 属性,这些属性将在 list 屏幕上显示您的命令时使用。

当执行命令时,将调用 handle 方法。您可以在此方法中放置任何命令逻辑。让我们看一个示例命令。

请注意,我们可以将任何需要的依赖项注入到命令的构造函数中。Laravel 服务容器 将自动注入构造函数中类型提示的所有依赖项。为了更大的代码重用性,最好保持控制台命令轻量,并让它们委托给应用程序服务来完成任务。

php
<?php

namespace App\Console\Commands;

use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;

class SendEmails extends Command
{
    /**
     * 控制台命令的名称和签名。
     *
     * @var string
     */
    protected $signature = 'email:send {user}';

    /**
     * 控制台命令的描述。
     *
     * @var string
     */
    protected $description = '向用户发送滴灌电子邮件';

    /**
     * 滴灌电子邮件服务。
     *
     * @var DripEmailer
     */
    protected $drip;

    /**
     * 创建新的命令实例。
     *
     * @param  DripEmailer  $drip
     * @return void
     */
    public function __construct(DripEmailer $drip)
    {
        parent::__construct();

        $this->drip = $drip;
    }

    /**
     * 执行控制台命令。
     *
     * @return mixed
     */
    public function handle()
    {
        $this->drip->send(User::find($this->argument('user')));
    }
}

命令 I/O

定义输入期望

在编写控制台命令时,通常需要通过参数或选项从用户那里收集输入。Laravel 使得定义用户期望的输入非常方便,您可以在命令的 signature 属性中定义。signature 属性允许您以一种简单、类似路由的语法定义命令的名称、参数和选项。

所有用户提供的参数和选项都用大括号括起来。在以下示例中,命令定义了一个必需参数:user

php
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user}';

您还可以使参数可选并为可选参数定义默认值:

php
// 可选参数...
email:send {user?}

// 带默认值的可选参数...
email:send {user=foo}

选项与参数一样,也是用户输入的一种形式。然而,它们在命令行中指定时以两个连字符(--)为前缀。我们可以在签名中这样定义选项:

php
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';

在此示例中,可以在调用 Artisan 命令时指定 --queue 开关。如果传递了 --queue 开关,选项的值将为 true。否则,值将为 false

php
php artisan email:send 1 --queue

您还可以通过在选项名称后加上 = 符号来指定选项应由用户分配一个值,表示应提供一个值:

php
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';

在此示例中,用户可以这样传递选项的值:

php
php artisan email:send 1 --queue=default

您还可以为选项分配默认值:

php
email:send {user} {--queue=default}

要在定义选项时分配快捷方式,您可以在选项名称之前指定它,并使用 | 分隔符将快捷方式与完整选项名称分开:

php
email:send {user} {--Q|queue}

如果您希望定义参数或选项以期望数组输入,可以使用 * 字符:

php
email:send {user*}

email:send {user} {--id=*}

输入描述

您可以通过使用冒号将参数与描述分开来为输入参数和选项分配描述:

php
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send
                        {user : 用户的 ID}
                        {--queue= : 是否应将作业排队}';

检索输入

在命令执行期间,您显然需要访问命令接受的参数和选项的值。为此,您可以使用 argumentoption 方法:

php
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $userId = $this->argument('user');

    //
}

如果您需要将所有参数作为 array 检索,请调用不带参数的 argument

php
$arguments = $this->argument();

选项可以像参数一样轻松检索,使用 option 方法。与 argument 方法一样,您可以调用不带任何参数的 option 以将所有选项作为 array 检索:

php
// 检索特定选项...
$queueName = $this->option('queue');

// 检索所有选项...
$options = $this->option();

如果参数或选项不存在,将返回 null

提示输入

除了显示输出,您还可以在命令执行期间要求用户提供输入。ask 方法将提示用户给定的问题,接受他们的输入,然后将用户的输入返回给您的命令:

php
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $name = $this->ask('What is your name?');
}

secret 方法类似于 ask,但用户的输入在控制台中输入时对他们不可见。此方法在询问密码等敏感信息时很有用:

php
$password = $this->secret('What is the password?');

请求确认

如果您需要向用户请求简单的确认,可以使用 confirm 方法。默认情况下,此方法将返回 false。但是,如果用户在提示中输入 y,该方法将返回 true

php
if ($this->confirm('Do you wish to continue? [y|N]')) {
    //
}

给用户一个选择

anticipate 方法可用于为可能的选择提供自动完成。用户仍然可以选择任何答案,无论自动完成提示如何:

php
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);

如果您需要给用户一个预定义的选择集,可以使用 choice 方法。用户选择答案的索引,但答案的值将返回给您。您可以设置默认值以在未选择任何内容时返回:

php
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $default);

输出信息

要将输出发送到控制台,请使用 lineinfocommentquestionerror 方法。每种方法都将使用适当的 ANSI 颜色来实现其目的。

要向用户显示信息消息,请使用 info 方法。通常,这将在控制台中显示为绿色文本:

php
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $this->info('Display this on the screen');
}

要显示错误消息,请使用 error 方法。错误消息文本通常以红色显示:

php
$this->error('Something went wrong!');

如果要显示普通控制台输出,请使用 line 方法。line 方法不会接收任何独特的颜色:

php
$this->line('Display this on the screen');

表格布局

table 方法使得正确格式化多行/列数据变得容易。只需将标题和行传递给该方法。宽度和高度将根据给定数据动态计算:

php
$headers = ['Name', 'Email'];

$users = App\User::all(['name', 'email'])->toArray();

$this->table($headers, $users);

进度条

对于长时间运行的任务,显示进度指示器可能会有所帮助。使用输出对象,我们可以启动、推进和停止进度条。您必须在启动进度时定义步骤数,然后在每个步骤后推进进度条:

php
$users = App\User::all();

$bar = $this->output->createProgressBar(count($users));

foreach ($users as $user) {
    $this->performTask($user);

    $bar->advance();
}

$bar->finish();

有关更高级的选项,请查看 Symfony Progress Bar 组件文档

注册命令

完成命令后,您需要在 Artisan 中注册它,以便可以使用它。这是在 app/Console/Kernel.php 文件中完成的。

在此文件中,您将在 commands 属性中找到命令列表。要注册命令,只需将类名添加到列表中。当 Artisan 启动时,服务容器将解析此属性中列出的所有命令并在 Artisan 中注册:

php
protected $commands = [
    Commands\SendEmails::class
];

通过代码调用命令

有时您可能希望在 CLI 之外执行 Artisan 命令。例如,您可能希望从路由或控制器触发 Artisan 命令。您可以使用 Artisan facade 上的 call 方法来实现这一点。call 方法接受命令名称作为第一个参数,并接受命令参数数组作为第二个参数。将返回退出代码:

php
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});

使用 Artisan facade 上的 queue 方法,您甚至可以将 Artisan 命令排队,以便它们由您的 队列工作者 在后台处理:

php
Route::get('/foo', function () {
    Artisan::queue('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});

如果您需要为不接受字符串值的选项指定值,例如 migrate:refresh 命令上的 --force 标志,您可以传递布尔值 truefalse

php
$exitCode = Artisan::call('migrate:refresh', [
    '--force' => true,
]);

从其他命令调用命令

有时您可能希望从现有的 Artisan 命令调用其他命令。您可以使用 call 方法来实现这一点。此 call 方法接受命令名称和命令参数数组:

php
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $this->call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
}

如果您希望调用另一个控制台命令并抑制其所有输出,可以使用 callSilent 方法。callSilent 方法的签名与 call 方法相同:

php
$this->callSilent('email:send', [
    'user' => 1, '--queue' => 'default'
]);