* * * * *
[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,任務,事件等等。運行?`tinker`?命令進入 Tinker 環境:
~~~
php artisan tinker
~~~
## 編寫命令
除了?`Artisan`?提供的命令之外,還可以創建自定義命令。自定義命令默認存儲在?`app/Console/Commands`?目錄,當然,你也可以修改?`composer.json`?配置來指定你想要存放的目錄。
### 生成命令
要創建一個新的命令,可以使用?`make:command`?命令。這個命令會創建一個命令類并存放在?`app/Console/Commands`目錄。 不必擔心不存在這個目錄,運行?`make:command`?命令時會首先創建這個目錄。生成的命令將會包括所有默認存在的屬性和方法:
~~~
php artisan make:command SendEmails
~~~
接下來,你需要在 Artisan CLI 里執行之前[注冊命令](Artisan命令行.md)。
### 命令結構
命令生成以后,應先填寫類的?`signature`?和?`description`?屬性,之后可以在使用?`list`?命令是顯示出來。執行命令是調用?`handle`?方法,可以把你的命令邏輯放到這個方法中。
> {tip} 大部分的代碼復用,保持你的代碼輕量并讓它們延遲到應用服務中完成任務是個不錯的實踐。在下面這個例子中,我們注入了一個服務類去執行發送郵件的繁重任務。
讓我們看這個簡單的命令例子,`Command`?類構造器允許注入需要的依賴,Laravel 的[服務容器](控制器.md)?將會自動注入構造函數中所有帶類型約束的依賴:
~~~
<?php
namespace App\Console\Commands;
use App\User;
use App\DripEmailer;
use Illuminate\Console\Command;
class SendEmails extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'email:send {user}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send drip e-mails to a user';
/**
* The drip e-mail service.
*
* @var DripEmailer
*/
protected $drip;
/**
* Create a new command instance.
*
* @param DripEmailer $drip
* @return void
*/
public function __construct(DripEmailer $drip)
{
parent::__construct();
$this->drip = $drip;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->drip->send(User::find($this->argument('user')));
}
}
~~~
### 閉包命令
閉包命令提供一個替代定義命令方法的類。同樣的路由閉包是控制器的一種替代方法,這種命令閉包可以替換命令類。使用?`app/Console/Kernel.php`?文件的?`commands`?方法,需要 Laravel 在?`routes/console.php`?注冊:
~~~
/**
* Register the Closure based commands for the application.
*
* @return void
*/
protected function commands()
{
require base_path('routes/console.php');
}
~~~
雖然這個文件沒有定義 HTTP 路由,它定義了基于控制臺的入口點(路由)到你的應用中,在這個文件中,你可以使用?`Artisan::command`?方法定義所有基于路由的閉包,`command`?方法接收兩個參數:[命令簽名](Artisan命令行.md)和一個接收命令參數和選項的閉包:
~~~
Artisan::command('build {project}', function ($project) {
$this->info("Building {$project}!");
});
~~~
閉包綁定下面的命令實例,因此你可以訪問所有的輔助方法,您也可以訪問一個完整的命令類。
#### 類型提示依賴
除了接收命令的參數和選項外,命令閉包也可以使用類型提示來指定?[服務容器](控制器.md)?之外的額外依賴:
~~~
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`?:
~~~
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'email:send {user}';
~~~
您也可以創建可選參數,并定義參數的默認值:
~~~
// Optional argument...
email:send {user?}
// Optional argument with default value...
email:send {user=foo}
~~~
### 選項
選項,和參數一樣,也是用戶輸入的一種格式,不過當使用選項時,需要在命令前加兩個連字符號 (`--`) 的前綴,有兩種類型的選項:接收一個值和不接受值。選項不接收一個值作為布爾值的?`switch`?。讓我們看一個選項的例子:
~~~
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'email:send {user} {--queue}';
~~~
在這個例子中,當調用?`Artisan`?命令時,`--queue`?這個選項可以被明確的指定。如果?`--queue`?被當成輸入時,這個選項的的值為?`true`?,否則這個值為?`false`?:
~~~
php artisan email:send 1 --queue
~~~
#### 有值的選項
接下來,我們看下有值的選項。如果用戶必須為選項指定一個值,會在選項的后面加一個?`=`?的后綴:
~~~
/**
* The name and signature of the console command.
*
* @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
~~~
### 輸入描述
您可以通過在使用一個冒號分離參數來分配輸入參數和選項的說明。如果你需要一個小的額外的空間來定義你的命令,可以多行定義你的擴展:
~~~
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'email:send
{user : The ID of the user}
{--queue= : Whether the job should be queued}';
~~~
## I/O 命令
### 獲取輸入
在命令執行的時,你可以像下面這樣使用?`argument`?和?`option`?方法獲取參數和選項:
~~~
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$userId = $this->argument('user');
//
}
~~~
如果您需要獲取所有參數作為一個?`array`,調用?`arguments`?方法:
~~~
$arguments = $this->arguments();
~~~
選項可以像參數一樣使用?`option`?方法檢索, 獲取所有的選項作為一個?`array`?,調用?`options`?方法:
~~~
// Retrieve a specific option...
$queueName = $this->option('queue');
// Retrieve all options...
$options = $this->options();
~~~
如果參數或選項不存在,將會返回?`null`?。
### 交互式輸入
除了顯示輸出,您還可以要求用戶在您的命令執行過程中提供輸入。`ask`?方法將會使用給定問題提示用戶,接收輸入,然后返回用戶輸入到命令:
~~~
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$name = $this->ask('What is your name?');
}
~~~
`secret`?方法和?`ask`?方法類似,但是用戶輸入在終端中是不可以見的,這個方法在需要用戶輸入像密碼這樣的敏感信息是很有用的:
~~~
$password = $this->secret('What is the password?');
~~~
#### 請求確認
如果你要用戶提供的確認信息,你可以使用?`confirm`?方法,默認情況下,該方法返回?`false`,當然,如果你輸入?`y`?這個方法將會返回?`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`?方法。通常,在終端顯示為綠色:
~~~
/**
* Execute the console command.
*
* @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 組件的文檔](https://symfony.com/doc/2.7/components/console/helpers/progressbar.html).
## 注冊命令
命令編寫完成后,需要注冊 Artisan 后才能使用。注冊文件為?`app/Console/Kernel.php`?。在這個文件中, 你會在?`commands`?屬性中看到一個命令列表。要注冊你的命令,只需將其加到該列表中即可。當 Artisan 啟動時,所有羅列在這個 屬性的命令,都會被?[服務容器](控制器.md)?解析并向 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 命令給后臺的?[隊列服務器](隊列.md)?運行,在這之前,確保您已配置了您的隊列,并正在運行隊列:
~~~
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`?方法接受命令名稱和命令參數的數組:
~~~
/**
* Execute the console command.
*
* @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
- HTTP層
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- Session
- 表單驗證
- 前端
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 錯誤與日志
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Scout 全文搜索
- Socialite 社會化登錄