# 服務 —— Artisan 控制臺
## 1、簡介
Artisan行接口名稱,它為你在開發過程中提供了很多有用的命令。通過強大的Symfony?Console組件驅動。想要查看所有可用的Artisan命令,可使用`list`命令:
~~~
php artisan list
~~~
每個命令都可以用`help`指令顯示命令描述及命令參數和選項。想要查看幫助界面,只需要在命令前加上`help`就可以了:
~~~
php artisan help migrate
~~~
## 2、編寫命令
除了Artisan提供的命令之外,還可以構建自己的命令。你可以將自定義命令存放在`app/Console/Commands`目錄;當然,你可以自己選擇存放位置,只要改命令可以基于`composer.json`被自動加載。
要創建一個新命令,你可以使用Artisan命令`make:console`:
~~~
php artisan make:console SendEmails
~~~
上述命令將會生成一個類`app/Console/Commands/SendEmails.php`,當創建命令時,`--command`選項可用于分配終端命令名(在終端調用命令時用):
~~~
php artisan make:console SendEmails --command=emails:send
~~~
### 2.1 命令結構
命令生成以后,需要填寫該類的`signature`和`description`屬性,這兩個屬性在調用`list`顯示命令的時候會被用到。
`handle`方法在命令執行時被調用,你可以將所有命令邏輯都放在這個方法里面,讓我們先看一個命令例子。
我們可以在命令控制器的構造函數中注入任何依賴,Laravel[服務提供者](http://laravelacademy.org/post/91.html)將會在構造函數中自動注入所有依賴類型提示。要增強代碼的復用性,保持代碼輕量級并讓它們延遲到應用服務中完成任務是個不錯的實踐:
~~~
<?php
namespace App\Console\Commands;
use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;
class Inspire extends Command{
/**
* 控制臺命令名稱
*
* @var string
*/
protected $signature = 'email:send {user}';
/**
* 控制臺命令描述
*
* @var string
*/
protected $description = 'Send drip e-mails to a user';
/**
* The drip e-mail service.
*
* @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')));
}
}
~~~
## 3、命令I/O?
### 3.1 定義輸入異常
編寫控制臺命令的時候,通常通過參數和選項收集用戶輸入,Laravel使這項操作變得很方便:在命令中使用`signature`屬性來定義我們期望的用戶輸入。`signature`屬性通過一個優雅的、路由風格的語法允許你定義命令的名稱、參數以及選項。所有用戶提供的參數和選項都包含在大括號里:
~~~
/**
* 控制臺命令名稱
*
* @var string
*/
protected $signature = 'email:send {user}';
~~~
在本例中,該命令定義了一個必須參數:`user`。你還可以讓參數可選化并定義默認的可選參數值:
~~~
// 選項參數...
email:send {user?}
// 帶默認值的選項參數...
email:send {user=foo}
~~~
選項,和參數一樣,也是用戶輸入的一種格式,不同之處在于選項前面有兩個短劃線(–),我們可以這樣定義選項:
~~~
/**
* 控制臺命令名稱
*
* @var string
*/
protected $signature = 'email:send {user} {--queue}';
~~~
在本例中,`--queue`開關在調用Artisan命令的時候被指定。如果`--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}
~~~
### 3.1.1 輸入描述
你可以通過:分隔參數和描述來分配描述給輸入參數和選項:
~~~
/**
* 控制臺命令名稱
*
* @var string
*/
protected $signature = 'email:send
{user : The ID of the user}
{--queue= : Whether the job should be queued}';
~~~
### 3.2 獲取輸入
在命令被執行的時候,很明顯,你需要訪問命令獲取的參數和選項的值。使用`argument`和`option`方法即可實現:
要獲取參數的值,通過`argument`方法:
~~~
/**
* 執行控制臺命令
*
* @return mixed
*/
public function handle(){
$userId = $this->argument('user');
}
~~~
如果你需要以數組形式獲取所有參數值,使用不帶參數的`argument`:
~~~
$arguments = $this->argument();
~~~
選項值和參數值的獲取一樣簡單,使用`option`方法,同`argument`一樣如果要獲取所有選項值,可以調用不帶參數的`option`方法:
~~~
// 獲取指定選項...
$queueName = $this->option('queue');
// 獲取所有選項...
$options = $this->option();
~~~
如果參數或選項不存在,返回null。
### 3.3 輸入提示
除了顯示輸出之外,你可能還要在命令執行期間要用戶提供輸入。`ask`?方法將會使用給定問題提示用戶,接收輸入,然后返回用戶輸入到命令:
~~~
/**
* 執行控制臺命令
*
* @return mixed
*/
public function handle(){
$name = $this->ask('What is your name?');
}
~~~
`secret`方法和`ask`方法類似,但用戶輸入在終端對他們而言是不可見的,這個方法在問用戶一些敏感信息如密碼時很有用:
~~~
$password = $this->secret('What is the password?');
~~~
### 3.3.1 讓用戶確認
如果你需要讓用戶確認信息,可以使用`confirm`方法,默認情況下,該方法返回`false`,如果用戶輸入`y`,則該方法返回`true`:
~~~
if ($this->confirm('Do you wish to continue? [y|N]')) {
//
}
~~~
### 3.3.2 給用戶提供選擇
`anticipate`方法可用于為可能的選項提供自動完成功能,用戶仍然可以選擇答案,而不管這些選擇:
~~~
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);
~~~
如果你需要給用戶預定義的選擇,可以使用`choice`方法。用戶選擇答案的索引,但是返回給你的是答案的值。如果用戶什么都沒選的話你可以設置默認返回的值:
~~~
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], false);
~~~
### 3.4 編寫輸出
要將輸出發送到控制臺,使用`info`,?`comment`,?`question`?和?`error`方法,每個方法都會使用相應的ANSI顏色以作標識。
要顯示一條信息消息給用戶,使用`info`方法。通常,在終端顯示為綠色:
~~~
/**
* 執行控制臺命令
*
* @return mixed
*/
public function handle(){
$this->info('Display this on the screen');
}
~~~
要顯示一條錯誤消息,使用`error`方法。錯誤消息文本通常是紅色:
~~~
$this->error('Something went wrong!');
~~~
### 3.4.1 表格布局
`table`?方法使輸出多行/列格式的數據變得簡單,只需要將頭和行傳遞給該方法,寬度和高度將基于給定數據自動計算:
~~~
$headers = ['Name', 'Email'];
$users = App\User::all(['name', 'email'])->toArray();
$this->table($headers, $users);
~~~
### 3.4.2 進度條
對需要較長時間運行的任務,顯示進度指示器很有用,使用該輸出對象,我們可以開始、前進以及停止該進度條。在開始進度時你必須定義定義步數,然后每走一步進度條前進一格:
~~~
$users = App\User::all();
$this->output->progressStart(count($users));
foreach ($users as $user) {
$this->performTask($user);
$this->output->progressAdvance();
}
$this->output->progressFinish();
~~~
想要了解更多,查看[Symfony進度條組件文檔](http://symfony.com/doc/2.7/components/console/helpers/progressbar.html)。
## 4、注冊命令
命令編寫完成后,需要注冊到Artisan才可以使用,這可以在`app/Console/Kernel.php`文件中完成。
在該文件中,你會在`commans`屬性中看到一個命令列表,要注冊你的命令,只需將加到該列表中即可。當Artisan啟動的時候,該屬性中列出的命令將會被[服務容器](http://laravelacademy.org/post/93.html)解析被注冊到Artisan:
~~~
protected $commands = [
'App\Console\Commands\SendEmails'
];
~~~
## 5、通過代碼調用命令
有時候你可能希望在CLI之外執行Artisan命令,比如,你可能希望在路由或控制器中觸發Artisan命令,你可以使用Artisan門面上的`call`方法來完成這個。`call`方法接收被執行的命令名稱作為第一個參數,命令參數數組作為第二個參數,退出代碼被返回:
~~~
Route::get('/foo', function () {
$exitCode = Artisan::call('email:send', [
'user' => 1, '--queue' => 'default'
]);
});
~~~
使用Artisan上的`queue`方法,你甚至可以將Artisan命令放到隊列中,這樣它們就可以通過后臺的[隊列工作者](http://laravelacademy.org/post/222.html)來處理:
~~~
Route::get('/foo', function () {
Artisan::queue('email:send', [
'user' => 1, '--queue' => 'default'
]);
});
~~~
如果你需要指定不接收字符串的選項值,例如`migrate:refresh`命令上的`--force`標識,可以傳遞布爾值`true`或`false`:
~~~
$exitCode = Artisan::call('migrate:refresh', [
'--force' => true,
]);
~~~
### 5.1?通過其他命令調用命令
有時候你希望從一個已存在的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'
]);
~~~
- 前言
- 序言
- 序言 ―― 發行版本說明
- 序言 ―― 升級指南
- 序言 ―― 貢獻代碼
- 開始
- 開始 ―― 安裝及配置
- 開始 ―― Laravel Homestead
- 基礎
- 基礎 ―― HTTP路由
- 基礎 ―― HTTP 中間件
- 基礎 ―― HTTP 控制器
- 基礎 ―― HTTP 請求
- 基礎 ―― HTTP 響應
- 基礎 ―― 視圖
- 基礎 ―― Blade模板
- 架構
- 架構 ―― 一次請求的生命周期
- 架構 ―― 應用目錄結構
- 架構 ―― 服務提供者
- 架構 ―― 服務容器
- 架構 ―― 契約
- 架構 ―― 門面
- 數據庫
- 數據庫 ―― 起步
- 數據庫 ―― 查詢構建器
- 數據庫 ―― 遷移
- 數據庫 ―― 填充數據
- Eloquent ORM
- Eloquent ORM ―― 起步
- Eloquent ORM ―― 關聯關系
- Eloquent ORM ―― 集合
- Eloquent ORM ―― 調整器
- Eloquent ORM ―― 序列化
- 服務
- 服務 ―― 用戶認證
- 服務 ―― Artisan 控制臺
- 服務 ―― Laravel Cashier(交易)
- 服務 ―― 緩存
- 服務 ―― 集合
- 服務 ―― Laravel Elixir
- 服務 ―― 加密
- 服務 ―― 錯誤&日志
- 服務 ―― 事件
- 服務 ―― 文件系統/云存儲
- 服務 ―― 哈希
- 服務 ―― 幫助函數
- 服務 ―― 本地化
- 服務 ―― 郵件
- 服務 ―― 包開發
- 服務 ―― 分頁
- 服務 ―― 隊列
- 服務 ―― Redis
- 服務 ―― Session
- 服務 ―― Envoy 任務運行器(SSH任務)
- 服務 ―― 任務調度
- 服務 ―― 測試
- 服務 ―― 驗證