* * * * *
[TOC]
## 簡介
Artisan 是 Laravel 自帶的命令行接口,它提供了許多實用的命令來幫助你構建 Laravel 應用。要查看所有可用的 Artisan 命令的列表,可以使用?`list`?命令:
~~~
php artisan list
~~~
每個命令包含了「幫助」界面,它會顯示并概述命令的可用參數及選項。只需要在命令前面加上?`help`?即可查看命令幫助界面:
~~~
php artisan help migrate
~~~
#### Laravel REPL
所有 Laravel 應用都包含了 Tinker,一個基于?[PsySH](https://github.com/bobthecow/psysh)?包提供支持的 REPL。 Tinker 讓你可以在命令行中與你整個的 Laravel 應用進行交互,包括 Eloquent ORM、任務、事件等等。運行 Artisan 命令?`tinker`?進入 Tinker 環境:
~~~
php artisan tinker
~~~
## 編寫命令
除 Artisan 提供的命令外,您還可以構建自己的自定義命令。 命令通常存儲在?`app/Console/Commands`?目錄中; 不過,只要您的命令可以由Composer 加載,您就可以自由選擇自己的存儲位置。
### 生成命令
要創建一個新的命令,可以使用 Artisan 命令?`make:command`。這個命令會在?`app/Console/Commands`?目錄中創建一個新的命令類。 不必擔心應用中不存在這個目錄,因為它會在你第一次運行 Artisan 命令?`make:command`?時創建。生成的命令會包括所有命令中默認存在的屬性和方法:
~~~
php artisan make:command SendEmails
~~~
### 命令結構
命令生成后,應先填寫類的?`signature`?和?`description`?屬性,這會在使用?`list`?命令的時候顯示出來。執行命令時會調用?`handle`?方法,你可以在這個方法中放置命令邏輯。
> {tip} 為了更好的代碼復用,最好保持你的控制臺代碼輕量并讓它們延遲到應用服務中完成。在下面的例子中,請注意,我們注入了一個服務類來完成發送郵件的「重任」。
讓我們看一個簡單的例子。注意,我們可以在 Command 的構造函數中注入我們需要的任何依賴項。Laravel?[服務容器](http://www.hmoore.net/tonyyu/laravel_5_6/786056)?將會自動注入所有在構造函數中的帶類型約束的依賴:
~~~
<?php
namespace App\Console\Commands;
use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;
class SendEmails extends Command
{
/**
* 控制臺命令 signature 的名稱。
*
* @var string
*/
protected $signature = 'email:send {user}';
/**
* 控制臺命令說明。
*
* @var string
*/
protected $description = 'Send drip e-mails to a user';
/**
* 郵件服務的 drip 屬性。
*
* @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`?方法接收兩個參數:[命令簽名](http://www.hmoore.net/tonyyu/laravel_5_6/786238#_150)?和一個接收命令參數和選項的閉包:
~~~
Artisan::command('build {project}', function ($project) {
$this->info("Building {$project}!");
});
~~~
閉包綁定底層的命令實例,因此你可以完全訪問通常可以在完整命令類中訪問的所有輔助方法。
#### 類型提示依賴
除了接收命令的參數和選項外,命令閉包也可以使用類型提示從?[服務容器](http://www.hmoore.net/tonyyu/laravel_5_6/786056)?中解析你想要的其他依賴關系:
~~~
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`
~~~
/**
* 控制臺命令 signature 的名稱。
*
* @var string
*/
protected $signature = 'email:send {user}';
~~~
你也可以創建可選參數,并定義參數的默認值:
~~~
// 可選參數...
email:send {user?}
// 帶有默認值的可選參數...
email:send {user=foo}
~~~
### 選項
選項,如參數,是用戶輸入的另一種格式。當命令行指定選項時,它們以兩個連字符(?`--`?)作為前綴。有兩種類型的選項:接收值和不接收值。不接收值的選項作為布爾值的「開關」。讓我們看一下這種類型的選項的例子:
~~~
/**
* 控制臺命令 `signature` 的名稱。
*
* @var string
*/
protected $signature = 'email:send {user} {--queue}';
~~~
在這個例子中,可以在調用 Artisan 時指定?`--queue`?開關。如果?`--queue`?開關被傳遞, 該選項的值為?`true`?,否則為?`false`:
~~~
php artisan email:send 1 --queue
~~~
#### 帶值的選項
接下來,我們來看一個帶值的選項。如果用戶必須為選項指定一個值,需要用一個等號?`=`?作為選項名稱的后綴:
~~~
/**
* 控制臺命令 signature 的名稱。
*
* @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
~~~
### 輸入說明
你可以通過冒號為參數和選項添加說明。如果你需要一點額外的空間來定義你的命令,可以隨意分開在多個行里:
~~~
/**
* 控制臺命令和 signature 屬性
*
* @var string
*/
protected $signature = 'email:send
{user : The ID of the user}
{--queue= : Whether the job should be queued}';
~~~
## I/O 命令
### 檢索輸入
在執行命令時,顯然你需要訪問命令的參數和選項的值。此時,你可以使用?`argument`?和?`option`?方法:
~~~
/**
* 執行控制臺命令
*
* @return mixed
*/
public function handle()
{
$userId = $this->argument('user');
//
}
~~~
如果你需要將所有參數以?`array`?檢索,可以調用?`arguments`?方法:
~~~
$arguments = $this->arguments();
~~~
`option`?方法可以非常容易的檢索參數選項。要將所有選項作為 array 檢索,可以使用?`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'], $defaultIndex);
~~~
### 編寫輸出
可以使用?`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);
~~~
#### 進度條
對于耗時任務,提示進度非常有必要。使用 output 對象就可以創建、加載以及停止進度條。首先,定義好任務總步數,然后,在每次任務執行時加載進度條:
~~~
$users = App\User::all();
$bar = $this->output->createProgressBar(count($users));
foreach ($users as $user) {
$this->performTask($user);
$bar->advance();
}
$bar->finish();
~~~
參閱?[Symfony 進度條組件文檔](https://symfony.com/doc/2.7/components/console/helpers/progressbar.html)?獲取更多高級用法。
## 注冊命令
`app/Console/Commands`?目錄下的命令都會被注冊,這是由于控制臺內核的?`commands`?方法調用了?`load`。實際上,可隨意調用?`load`?來掃描其他目錄下的 Artisan 命令:
~~~
/**
* 注冊應用的命令
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->load(__DIR__.'/MoreCommands');
// ...
}
~~~
也可以在?`app/Console/Kernel.php`?文件的?`$commands`?屬性中手動注冊命令的類名。Artisan 啟動時,這個屬性列出的命令都將由?[服務容器](http://www.hmoore.net/tonyyu/laravel_5_6/786056)?解析并通過 Artisan 進行注冊:
~~~
protected $commands = [
Commands\SendEmails::class
];
~~~
## 程序調用命令
有時需要在 CLI 之外執行 Artisan 命令,例如,在路由或控制器里觸發 Artisan 命令。要實現調用,可以使用?`Artisan`門面的?`call`?方法。`call`?方法的第一個參數接受命令名,第二個參數接受數組形式的命令參數。退出碼將返回:
~~~
Route::get('/foo', function () {
$exitCode = Artisan::call('email:send', [
'user' => 1, '--queue' => 'default'
]);
//
});
~~~
`Artisan`?門面的?`queue`?方法可以將 Artisan 命令隊列化,交由?[隊列工作進程](http://www.hmoore.net/tonyyu/laravel_5_6/786248)?進行后臺處理。使用此方法之前,務必配置好隊列以及運行隊列監聽器:
~~~
Route::get('/foo', function () {
Artisan::queue('email:send', [
'user' => 1, '--queue' => 'default'
]);
//
});
~~~
可以指定 Artisan 命令派發的連接或任務:
~~~
Artisan::queue('email:send', [
'user' => 1, '--queue' => 'default'
])->onConnection('redis')->onQueue('commands');
~~~
#### 傳遞數組值
如果定義了接受數組的選項,可以直接傳遞數組到該選項:
~~~
Route::get('/foo', function () {
$exitCode = Artisan::call('email:send', [
'user' => 1, '--id' => [5, 13]
]);
});
~~~
#### 傳遞布爾值
需要指定沒有選項值的選項時,例如,`migrate:refresh`?命令的?`--force`?選項,就可以傳入?`true`?或?`false`:
~~~
$exitCode = Artisan::call('migrate:refresh', [
'--force' => true,
]);
~~~
### 命令的互相調用
`call`?方法可以實現調用其它 Artisan 命令。`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'
]);
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄