Artisan 控制台 
介绍 
Artisan 是 Laravel 附带的命令行界面。它提供了许多有用的命令,可以在您构建应用程序时为您提供帮助。要查看所有可用的 Artisan 命令列表,您可以使用 list 命令:
php artisan list每个命令还包括一个“帮助”屏幕,其中显示并描述了命令的可用参数和选项。要查看帮助屏幕,只需在命令名称前加上 help:
php artisan help migrateLaravel REPL 
所有 Laravel 应用程序都包含 Tinker,这是一个由 PsySH 包提供支持的 REPL。Tinker 允许您在命令行上与整个 Laravel 应用程序进行交互,包括 Eloquent ORM、作业、事件等。要进入 Tinker 环境,请运行 tinker Artisan 命令:
php artisan tinker编写命令 
除了 Artisan 提供的命令之外,您还可以构建自己的自定义命令。命令通常存储在 app/Console/Commands 目录中;但是,只要您的命令可以由 Composer 加载,您可以自由选择自己的存储位置。
生成命令 
要创建新命令,请使用 make:command Artisan 命令。此命令将在 app/Console/Commands 目录中创建一个新的命令类。如果您的应用程序中不存在此目录,请不要担心,因为它将在您第一次运行 make:command Artisan 命令时创建。生成的命令将包括所有命令中存在的默认属性和方法集:
php artisan make:command SendEmails接下来,您需要注册命令,然后才能通过 Artisan CLI 执行它。
命令结构 
生成命令后,您应填写类的 signature 和 description 属性,这些属性将在 list 屏幕上显示您的命令时使用。执行命令时将调用 handle 方法。您可以将命令逻辑放在此方法中。
NOTE
为了更好地重用代码,最好保持控制台命令的简洁,并让它们委托给应用程序服务来完成任务。在下面的示例中,请注意我们注入了一个服务类来完成发送电子邮件的“繁重工作”。
让我们看一个示例命令。请注意,我们可以将任何需要的依赖项注入到命令的构造函数中。Laravel 服务容器 将自动注入构造函数中类型提示的所有依赖项:
<?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')));
    }
}闭包命令 
基于闭包的命令提供了定义控制台命令的类的替代方法。与路由闭包是控制器的替代方法一样,可以将命令闭包视为命令类的替代方法。在 app/Console/Kernel.php 文件的 commands 方法中,Laravel 加载 routes/console.php 文件:
/**
 * 为应用程序注册基于闭包的命令。
 *
 * @return void
 */
protected function commands()
{
    require base_path('routes/console.php');
}即使此文件未定义 HTTP 路由,它也定义了进入应用程序的基于控制台的入口点(路由)。在此文件中,您可以使用 Artisan::command 方法定义所有基于闭包的路由。command 方法接受两个参数:命令签名和接收命令参数和选项的闭包:
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
});闭包绑定到底层命令实例,因此您可以完全访问通常可以在完整命令类上访问的所有辅助方法。
类型提示依赖项 
除了接收命令的参数和选项外,命令闭包还可以类型提示您希望从服务容器中解析的其他依赖项:
use App\User;
use App\DripEmailer;
Artisan::command('email:send {user}', function (DripEmailer $drip, $user) {
    $drip->send(User::find($user));
});闭包命令描述 
定义基于闭包的命令时,您可以使用 describe 方法为命令添加描述。当您运行 php artisan list 或 php artisan help 命令时,将显示此描述:
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
})->describe('Build the project');定义输入期望 
编写控制台命令时,通常需要通过参数或选项从用户那里收集输入。Laravel 使您可以非常方便地使用命令上的 signature 属性定义您期望用户提供的输入。signature 属性允许您以单一、富有表现力的路由样式语法定义命令的名称、参数和选项。
参数 
所有用户提供的参数和选项都用大括号括起来。在以下示例中,命令定义了一个必需参数:user:
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user}';您还可以使参数可选并为参数定义默认值:
// 可选参数...
email:send {user?}
// 带默认值的可选参数...
email:send {user=foo}选项 
选项与参数一样,是另一种形式的用户输入。选项在命令行上指定时以两个连字符(--)为前缀。选项有两种类型:接收值的选项和不接收值的选项。不接收值的选项用作布尔“开关”。让我们看一个这种类型选项的示例:
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';在此示例中,可以在调用 Artisan 命令时指定 --queue 开关。如果传递了 --queue 开关,则选项的值将为 true。否则,值将为 false:
php artisan email:send 1 --queue带值的选项 
接下来,让我们看一个期望值的选项。如果用户必须为选项指定一个值,请在选项名称后加上 = 符号:
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';在此示例中,用户可以这样传递选项的值:
php artisan email:send 1 --queue=default您可以通过在选项名称后指定默认值来为选项分配默认值。如果用户未传递选项值,则将使用默认值:
email:send {user} {--queue=default}选项快捷方式 
要在定义选项时分配快捷方式,可以在选项名称之前指定它,并使用 | 分隔符将快捷方式与完整选项名称分开:
email:send {user} {--Q|queue}输入数组 
如果您希望定义参数或选项以期望数组输入,可以使用 * 字符。首先,让我们看一个指定数组参数的示例:
email:send {user*}调用此方法时,可以按顺序将 user 参数传递给命令行。例如,以下命令将 user 的值设置为 ['foo', 'bar']:
php artisan email:send foo bar定义期望数组输入的选项时,传递给命令的每个选项值都应以选项名称为前缀:
email:send {user} {--id=*}
php artisan email:send --id=1 --id=2输入描述 
您可以通过使用冒号将参数与描述分开来为输入参数和选项分配描述。如果您需要更多空间来定义命令,请随意将定义分布在多行上:
/**
 * 控制台命令的名称和签名。
 *
 * @var string
 */
protected $signature = 'email:send
                        {user : 用户的 ID}
                        {--queue= : 是否应将作业排队}';命令 I/O 
检索输入 
在命令执行期间,您显然需要访问命令接受的参数和选项的值。为此,您可以使用 argument 和 option 方法:
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $userId = $this->argument('user');
    //
}如果需要将所有参数作为 array 检索,请调用 arguments 方法:
$arguments = $this->arguments();选项可以像参数一样轻松检索,使用 option 方法。要将所有选项作为数组检索,请调用 options 方法:
// 检索特定选项...
$queueName = $this->option('queue');
// 检索所有选项...
$options = $this->options();如果参数或选项不存在,将返回 null。
提示输入 
除了显示输出之外,您还可以在命令执行期间要求用户提供输入。ask 方法将使用给定的问题提示用户,接受他们的输入,然后将用户的输入返回给您的命令:
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $name = $this->ask('What is your name?');
}secret 方法类似于 ask,但用户的输入在控制台中输入时对他们不可见。此方法在询问密码等敏感信息时很有用:
$password = $this->secret('What is the password?');请求确认 
如果您需要向用户询问简单的确认,可以使用 confirm 方法。默认情况下,此方法将返回 false。但是,如果用户在提示中输入 y 或 yes,则该方法将返回 true。
if ($this->confirm('Do you wish to continue?')) {
    //
}自动完成 
anticipate 方法可用于为可能的选择提供自动完成。用户仍然可以选择任何答案,而不管自动完成提示如何:
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);多项选择问题 
如果您需要为用户提供预定义的选择集,可以使用 choice 方法。您可以设置默认值,如果未选择任何选项,则返回该默认值:
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $default);写入输出 
要将输出发送到控制台,请使用 line、info、comment、question 和 error 方法。每种方法都将使用适当的 ANSI 颜色来实现其目的。例如,让我们向用户显示一些常规信息。通常,info 方法将在控制台中显示为绿色文本:
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $this->info('Display this on the screen');
}要显示错误消息,请使用 error 方法。错误消息文本通常以红色显示:
$this->error('Something went wrong!');如果您希望显示纯色、无色的控制台输出,请使用 line 方法:
$this->line('Display this on the screen');表格布局 
table 方法使得正确格式化多行/列数据变得容易。只需将标题和行传递给该方法。宽度和高度将根据给定数据动态计算:
$headers = ['Name', 'Email'];
$users = App\User::all(['name', 'email'])->toArray();
$this->table($headers, $users);进度条 
对于长时间运行的任务,显示进度指示器可能会有所帮助。使用输出对象,我们可以启动、推进和停止进度条。首先,定义进程将迭代的步骤总数。然后,在处理每个项目后推进进度条:
$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 启动时,commands 属性中列出的所有命令将由服务容器解析并在 Artisan 中注册:
protected $commands = [
    Commands\SendEmails::class
];以编程方式执行命令 
有时您可能希望在 CLI 之外执行 Artisan 命令。例如,您可能希望从路由或控制器触发 Artisan 命令。您可以使用 Artisan facade 上的 call 方法来实现此目的。call 方法接受命令名称作为第一个参数,并接受命令参数数组作为第二个参数。将返回退出代码:
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
    //
});使用 Artisan facade 上的 queue 方法,您甚至可以将 Artisan 命令排队,以便它们由您的队列工作者在后台处理。在使用此方法之前,请确保您已配置队列并正在运行队列监听器:
Route::get('/foo', function () {
    Artisan::queue('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
    //
});如果您需要为不接受字符串值的选项指定值,例如 migrate:refresh 命令上的 --force 标志,您可以传递 true 或 false:
$exitCode = Artisan::call('migrate:refresh', [
    '--force' => true,
]);从其他命令调用命令 
有时您可能希望从现有的 Artisan 命令调用其他命令。您可以使用 call 方法来实现。此 call 方法接受命令名称和命令参数数组:
/**
 * 执行控制台命令。
 *
 * @return mixed
 */
public function handle()
{
    $this->call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);
    //
}如果您希望调用另一个控制台命令并抑制其所有输出,可以使用 callSilent 方法。callSilent 方法的签名与 call 方法相同:
$this->callSilent('email:send', [
    'user' => 1, '--queue' => 'default'
]);