1、入門
Laravel通過Artisan提供了強大的控制台命令來處理非瀏覽器業務邏輯。要查看Laravel中所有的Artisan命令,可以通過在項目根目錄運行:
php artisan list
對應輸出如下(部分截圖):

其中一些命名我們已經比較熟悉了,比如創建遷移make:migration以及執行遷移migrate,又比如創建模型make:model,創建控制器make:controller等。
如果要查看具體某個命令的使用方法,比如我們要查看創建Artisan命令make:console的具體用法,可以使用如下命令:
php artisan help make:console
對應輸出如下:

2、創建命令
Artisan除了提供豐富的控制台命令之外,還允許我們通過make:console命令創建自己的控制台命令。上面我們已經使用help指令查看了make:console的用法,下面我們就沿着這條路走下去,一探究竟:創建命令並運行起來得到我們想要的各種結果。
首先我們創建一個最簡單的命令,打印Hello LaravelAcademy,使用Artisan命令如下:
php artisan make:console HelloLaravelAcademy --command=laravel:academy
其中HelloLaravelAcademy是命令名,laravel:academy是控制台執行的命令,類似make:console。
執行完成后,會在app/Console/Commands目錄下生成一個HelloLaravelAcademy.php文件:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class HelloLaravelAcademy extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'laravel:academy';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
}
}
其中$signature即為在控制台執行的命令名,$description為命令描述,handle方法為執行命令時調用的方法。
接下來我們簡單編寫handle方法如下:
public function handle()
{
echo "Hello LaravelAcademy\n";
}
好了,一個最簡單的命令已經編寫好了,接下來要怎么執行並在控制台打印出“Hello LaravelAcademy”呢?
3、運行命令
在運行命令前需要將其注冊到App\Console\Kernel的$commands屬性中:
protected $commands = [
... //其他命令類
\App\Console\Commands\HelloLaravelAcademy::class
];
接下來我們就可以在控制台運行如下Artisan命令:
php artisan laravel:academy
終端就會打印出:
Hello LaravelAcademy
是不是很簡單?
4、更多樣的輸入輸出
當然,上面是最簡單的情形,沒有輸入,寫死的輸出。實際環境中有更復雜的需求,有更多樣的輸入輸出,下面我們來一一討論。
定義輸入
上面已經提到,我們可以通過修改$signature屬性定義輸入參數及選項,比如這里我們將上述Hello后面的字符串調整為通過輸入參數來控制,可修改$signature如下:
protected $signature = 'laravel:academy {name}';
這樣定義意味着name是必選參數,當然還支持更多自定義參數輸入:
{name?} //可選參數
{name=LaravelAcademy} //默認name值為LaravelAcademy
為增強程序健壯性,我們將name修改為有默認值:
protected $signature = 'laravel:academy {name=LaravelAcademy}';
有時候我們還會在執行命令時傳入一些選項,比如是否顯示標點符號(雖然聽上去很雞肋,這里權當測試之用), 那么我們可以修改$signature屬性如下:
protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark}';
如果調用命令時傳遞--mark則代表其值為true,否則為false,如果選項值在輸入時通過用戶設置,可定義$signature如下:
protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark=}';
這樣用戶就可以在傳入選項時通過=來為選項賦值,當然和參數一樣,我們也可以為選項指定默認值:
protected $signature = 'laravel:academy {name=LaravelAcademy} {--mark=!}';
獲取輸入
定義好輸入參數和選項后,又該如何獲取其對應值呢?Laravel為我們提供了相應的方法。
獲取參數值可以通過Illuminate\Console\Command的argument方法:
$name = $this->argument('name');
如果無參調用argument方法,則返回的是所有參數值數組。
獲取選項值可以通過Illuminate\Console\Command的option方法:
$mark = $this->option('mark');
同理,無參調用option方法會返回所有選項值數組。
這樣我們可以修改HelloLaravelAcademy的handle方法如下:
public function handle()
{
$name = $this->argument('name');
$mark = $this->option('mark');
$string = 'Hello '.$name;
if($mark)
$string .= $mark;
echo $string."\n";
}
這樣我們在控制台輸入如下Artisan命令:
php artisan laravel:academy
對應輸出為:
Hello LaravelAcademy!
再運行如下Artisan命令:
php artisan laravel:academy Laravel --mark=?
對應輸出為:
Hello Laravel?
輸入提示
我們甚至還可以完全讓用戶通過在控制台輸入name來獲取輸入參數,首先修改handle方法如下:
public function handle()
{
$name = $this->ask('What do you want to say Hello?');
echo "Hello ".$name."\n";
}
然后在終端輸入php artisan laravel:academy,交互頁面如下:

如果是輸入密碼一類的敏感信息可以用secret替代ask方法。
有時候我們會根據用戶的意願選擇繼續還是中止:
public function handle()
{
if($this->confirm('Do you want to continue?[y|n]')){
$this->info("Continue");
}else{
$this->error("Interrupt");
}
}
對應輸出為:

除了讓用戶手動輸入外,還可以使用anticipate方法實現自動完成功能:
public function handle()
{
$name = $this->anticipate('What is your name?', ['Laravel', 'Academy']);
$this->info($name);
}
當然還可以使用choice方法為用戶提供選擇避免手動輸入,用戶只需選擇對應索引即可:
public function handle()
{
$name = $this->choice('What is your name?', ['Laravel', 'Academy']);
$this->info($name);
}
對應交互頁面如下:

編寫輸出
關於輸出字符串,上面我們簡單使用了echo語句,其實Laravel提供了更為強大和多樣化的方法:
public function handle()
{
$this->info("Successful!");
$this->error("Something Error!");
$this->question("What do you want to do?");
$this->comment("Just Comment it!");
}
執行php artisan laravel:academy對應輸出如下:

表格
Artisan甚至可以輸出表格:
public function handle()
{
$headers = ['Name', 'Email'];
$users = \App\User::all(['name', 'email'])->toArray();
$this->table($headers, $users);
}
執行php artisan laravel:academy對應輸出為:

當然對於復雜耗時的命令,進度條是必不可少的,
public function handle()
{
$this->output->progressStart(10);
for ($i = 0; $i < 10; $i++) {
sleep(1);
$this->output->progressAdvance();
}
$this->output->progressFinish();
}
執行php artisan laravel:academy對應輸出為:
![]()
5、從CLI之外調用Artisan
除了在控制台執行Artisan命令之外,還可以通過代碼在別處調用Artisan命令,比如其它Artisan命令、控制器、路由或其他。
路由
在路由閉包中我們可以通過Artisan門面的call方法來調用本節創建的命令:
//在路由中調用Artisan命令
Route::get('testArtisan',function(){
$exitCode = Artisan::call('laravel:academy', [
'name' => 'Laravel學院', '--mark' => '!'
]);
});
其它Artisan命令
在一個Artisan命令中也可以調用另一個Artisan命令,還是通過call方法:
public function handle()
{
$this->call('inspire');
}
如果想要調用一個Artisan命令並阻止其所有輸出,可以使用callSilent方法:
public function handle()
{
$this->callSilent('inspire');
}
號外:除此之外,關於Artisan命令你還應該知道的是我們可以在創建的命令類的控制器或方法中注入任何依賴。這就意味着我們可以在命令類中使用注冊到服務容器的所有類。
