Artisan 控制台
介绍
Artisan 是 Laravel 附带的命令行界面。它提供了许多有用的命令,可以在构建应用程序时为您提供帮助。要查看所有可用的 Artisan 命令列表,可以使用 list
命令:
php artisan list
每个命令还包括一个“帮助”屏幕,显示并描述命令的可用参数和选项。要查看帮助屏幕,只需在命令名称前加上 help
:
php artisan help migrate
Laravel 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
方法。您可以将命令逻辑放在此方法中。
为了更好的代码重用,建议保持控制台命令轻量,并让它们委托给应用程序服务来完成任务。在下面的示例中,请注意我们注入了一个服务类来完成发送电子邮件的“繁重工作”。
让我们看一个示例命令。请注意,我们可以将所需的任何依赖项注入到命令的构造函数中。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 启动时,服务容器将解析此属性中列出的所有命令并在 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'
]);