Artisan 主控台
簡介
Artisan 是 Laravel 內所包含的指令列界面。Artisan 是放在專案根目錄的 artisan
工序指令,提供多種實用指令來幫你撰寫你的專案。若要檢視所有可用的 Artisan 指令,可以使用 list
指令:
1php artisan list
1php artisan list
每個指令也包含了一個「help」畫面,用於顯示指令的說明以及可用的引數與選項。若要檢視輔助說明畫面,請在指令名稱的前面加上 help
:
1php artisan help migrate
1php artisan help migrate
Laravel Sail
若使用 Laravel Sail 作為本機開發環境,請記得使用 sail
指令列來叫用 Artisan 指令。Sail 會在專案的 Docker 容器內執行 Artisan 指令。
1./sail artisan list
1./sail artisan list
Tinker (REPL)
Laravel Tinker 是用於 Laravel 框架的強大 REPL,由 PsySH 套件提供。
安裝
所有的 Laravel 專案預設都包含了 Tinker。但若先前曾自專案內移除 Tinker,則可使用 Composer 來安裝:
1composer require laravel/tinker
1composer require laravel/tinker
想找個能與你的 Laravel 應用程式互動的圖形化 UI 嗎?試試 Tinkerwell 吧!
使用
Tinker 可讓你在指令列內與完整的 Laravel 專案進行互動,包含 Eloquent Model、任務、事件…等。要進入 Tinker 環境,請執行 tinker
Artisan 指令:
1php artisan tinker
1php artisan tinker
可以通過 vendor:publish
指令來安裝 Tinker 的設定檔:
1php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"
1php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"
dispatch
輔助函式與 Dispatchable
類別上的 dispatch
方法需要仰賴垃圾回收機制來將任務放進佇列中。因此,在使用 Tinker 時,應使用 Bus::dispatch
或 Queue::push
來分派任務。
指令允許列表
Tinker 使用一個「allow」清單來判斷哪些 Artisan 指令可在其 Shell 內執行。預設情況下,可以執行 clear-compiled
, down
, env
, inspire
, migrate
, optimize
以及 up
指令。若想允許更多指令,可以將要允許的指令加在 tinker.php
設定檔中的 commands
陣列內:
1'commands' => [2 // App\Console\Commands\ExampleCommand::class,3],
1'commands' => [2 // App\Console\Commands\ExampleCommand::class,3],
不應以別名使用的類別
一般來說,Tinker 會在使用過程中自動為類別加上別名。但有些類別可能不希望被設定別名。可以通過在 tinker.php
設定檔中的 dont_alias
陣列中列出這些不想被自動別名的類別來達成:
1'dont_alias' => [2 App\Models\User::class,3],
1'dont_alias' => [2 App\Models\User::class,3],
撰寫指令
除了 Artisan 提供的指令外,也可以建制自己的自訂指令。指令通常儲存於 app/Console/Commands
目錄內。但是,只要你的自訂指令可以被 Composer 載入,也可以自行選擇儲存位置。
產生指令
若要建立新指令,可以使用 make:command
Artisan 指令。該指令會在 app/Console/Commands
目錄下建立一個新的指令類別。若你的專案中沒有這個資料夾,請別擔心——第一次執行 make:command
Artisan 指令的時候會自動建立該資料夾:
1php artisan make:command SendEmails
1php artisan make:command SendEmails
指令結構
產生指令後,應為類別的 signature
與 description
屬性定義適當的值。當在 list
畫面內顯示該指令時,就會用到這些屬性。signature
屬性可以用來定義 指令預期的輸入。handle
方法會在執行該指令時呼叫。可以將指令的邏輯放在該方法內。
來看看一個範例指令。請注意,我們可以通過指令的 handle
方法來要求任意的相依性。Laravel 的 Service Container 會自動插入所有在方法簽章內有型別提示的相依性。
1<?php23namespace App\Console\Commands;45use App\Models\User;6use App\Support\DripEmailer;7use Illuminate\Console\Command;89class SendEmails extends Command10{11 /**12 * The name and signature of the console command.13 *14 * @var string15 */16 protected $signature = 'mail:send {user}';1718 /**19 * The console command description.20 *21 * @var string22 */23 protected $description = 'Send a marketing email to a user';2425 /**26 * Create a new command instance.27 *28 * @return void29 */30 public function __construct()31 {32 parent::__construct();33 }3435 /**36 * Execute the console command.37 *38 * @param \App\Support\DripEmailer $drip39 * @return mixed40 */41 public function handle(DripEmailer $drip)42 {43 $drip->send(User::find($this->argument('user')));44 }45}
1<?php23namespace App\Console\Commands;45use App\Models\User;6use App\Support\DripEmailer;7use Illuminate\Console\Command;89class SendEmails extends Command10{11 /**12 * The name and signature of the console command.13 *14 * @var string15 */16 protected $signature = 'mail:send {user}';1718 /**19 * The console command description.20 *21 * @var string22 */23 protected $description = 'Send a marketing email to a user';2425 /**26 * Create a new command instance.27 *28 * @return void29 */30 public function __construct()31 {32 parent::__construct();33 }3435 /**36 * Execute the console command.37 *38 * @param \App\Support\DripEmailer $drip39 * @return mixed40 */41 public function handle(DripEmailer $drip)42 {43 $drip->send(User::find($this->argument('user')));44 }45}
為了提升程式碼重複使用率,最好保持主控台指令精簡,並將指令的任務委託給應用程式服務來完成。在上方的例子中,可以注意到我們插入了一個服務類別來處理寄送 E-Mail 的這個「重責大任」。
閉包指令
基於閉包的指令提供了以類別定義主控台指令外的另一個選擇。就如同使用閉包來定義路由可用來代替控制器一樣,可以將指令閉包想象成是指令類別的代替。在 app/Console/Kernel.php
檔中的 commands
方法內,Laravel 載入了 routes/console.php
檔:
1/**2 * Register the closure based commands for the application.3 *4 * @return void5 */6protected function commands()7{8 require base_path('routes/console.php');9}
1/**2 * Register the closure based commands for the application.3 *4 * @return void5 */6protected function commands()7{8 require base_path('routes/console.php');9}
這個檔案並沒有定義 HTTP 路由,而是定義從主控台「路由」進入專案的進入點。在該檔案內,可以通過 Artisan::command
方法來定義基於閉包的主控台指令。command
方法接受 2 個引數:指令簽章,以及一個用來接收指令引數與選項的閉包:
1Artisan::command('mail:send {user}', function ($user) {2 $this->info("Sending email to: {$user}!");3});
1Artisan::command('mail:send {user}', function ($user) {2 $this->info("Sending email to: {$user}!");3});
這裡的閉包有綁定到該指令的基礎類別執行個體,因此可以像在完整的指令類別內一樣存取所有的輔助函式。
對相依關係進行型別提示
除了接收指令的引數與選項外,指令閉包也可以通過型別提示來向 Service Container 解析額外的相依關係。
1use App\Models\User;2use App\Support\DripEmailer;34Artisan::command('mail:send {user}', function (DripEmailer $drip, $user) {5 $drip->send(User::find($user));6});
1use App\Models\User;2use App\Support\DripEmailer;34Artisan::command('mail:send {user}', function (DripEmailer $drip, $user) {5 $drip->send(User::find($user));6});
閉包指令描述
在定義基於閉包的指令時,可以使用 purpose
方法來為該指令加上描述。這段描述會在執行 php artisan list
或 php artisan help
指令時顯示:
1Artisan::command('mail:send {user}', function ($user) {2 // ...3})->purpose('Send a marketing email to a user');
1Artisan::command('mail:send {user}', function ($user) {2 // ...3})->purpose('Send a marketing email to a user');
定義預期的輸入
在撰寫主控台指令時,常常會通過引數或選項來向使用者取得輸入。Laravel 通過指令的 signature
屬性來定義預期從使用者那取得的輸入,讓這個過程變得非常簡單。通過 signature
屬性,就能通過類似路由的格式來一次定義名稱、引數,以及選項。非常簡潔有力。
引數
所有由使用者提供的引數與選項都以大括號來包裝。在下列範例中的指令定義了一個必要的引數:user
:
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user}';
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user}';
也可以將引數設為可選,或是定義引數的預設值:
1// Optional argument...2mail:send {user?}34// Optional argument with default value...5mail:send {user=foo}
1// Optional argument...2mail:send {user?}34// Optional argument with default value...5mail:send {user=foo}
選項
選項就像引數一樣,是另一種形式的使用者輸入。選項在從指令列提供時,會加上兩個減號 (--
) 作為前綴。有兩種類型的選項:一種可接收值,一種沒有接收值。沒有接收值的選項是一種布林「開關」功能。來看看一個使用這種類型選項的例子:
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user} {--queue}';
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user} {--queue}';
在這個例子中,呼叫該 Artisan 指令時可以指定 --queue
開關。若有傳入 --queue
開關,則該選項的值會是 true
。否則,該值為 false
:
1php artisan mail:send 1 --queue
1php artisan mail:send 1 --queue
帶值的選項
接下來,來看看有值的選項。若使用者必須為選項指定一個值,則應在選項名稱後方加上 =
符號:
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user} {--queue=}';
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send {user} {--queue=}';
在這個例子中,使用者可以傳入像這樣給選項帶入一個值。若在叫用該指令時未指定該選項,則其值為 null
:
1php artisan mail:send 1 --queue=default
1php artisan mail:send 1 --queue=default
可以通過在選項名稱後方加上預設值來為選項指派一個預設值。若使用者未傳入選項值,將會使用預設值:
1mail:send {user} {--queue=default}
1mail:send {user} {--queue=default}
選項捷徑
若要在定義選項時指定捷徑,可以在選項名稱前加上其捷徑名稱,並使用 |
字元來區分捷徑名稱與完整的選項名稱:
1mail:send {user} {--Q|queue}
1mail:send {user} {--Q|queue}
在終端機內叫用指令時,應在選項捷徑前加上一個減號:
1php artisan mail:send 1 -Q
1php artisan mail:send 1 -Q
輸入陣列
若想要定義預期有多個輸入值的引數或選項,則可以使用 *
字元。首先,來看看這樣設定引數的例子:
1mail:send {user*}
1mail:send {user*}
呼叫這個方法的時候,user
引數在指令列中可以按照順序傳入。舉例來說,下列指令會將 user
的值設為一個內容為 foo
與 bar
的陣列:
1php artisan mail:send foo bar
1php artisan mail:send foo bar
*
字元可以與可選引數組合使用來定義,這樣一來可允許有 0 個或多個引數的實體:
1mail:send {user?*}
1mail:send {user?*}
選項陣列
定義預期有多個輸入值的選項時,每個傳入指令的選項值都應以選項名稱作為前綴:
1mail:send {user} {--id=*}23php artisan mail:send --id=1 --id=2
1mail:send {user} {--id=*}23php artisan mail:send --id=1 --id=2
輸入描述
可以通過以冒號 (:
) 區分引數名與描述來為輸入引數或選項指定描述。若需要更多空間來定義指令的話,可以將定義拆分為多行:
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send7 {user : The ID of the user}8 {--queue : Whether the job should be queued}';
1/**2 * The name and signature of the console command.3 *4 * @var string5 */6protected $signature = 'mail:send7 {user : The ID of the user}8 {--queue : Whether the job should be queued}';
指令 I/O
截取輸入
指令執行時,我們通常需要存取這些指令所接收的引數與選項值。要截取這些值,可以使用 argument
與 option
方法。若引數或選項不存在,則會回傳 null
:
1/**2 * Execute the console command.3 *4 * @return int5 */6public function handle()7{8 $userId = $this->argument('user');910 //11}
1/**2 * Execute the console command.3 *4 * @return int5 */6public function handle()7{8 $userId = $this->argument('user');910 //11}
若要將所有引數截取為陣列,則可呼叫 arguments
方法:
1$arguments = $this->arguments();
1$arguments = $this->arguments();
我們也可像截取引數一樣使用 option
方法來輕鬆地截取選項。若要將所有選項截取為陣列,請呼叫 options
方法:
1// Retrieve a specific option...2$queueName = $this->option('queue');34// Retrieve all options as an array...5$options = $this->options();
1// Retrieve a specific option...2$queueName = $this->option('queue');34// Retrieve all options as an array...5$options = $this->options();
為輸入進行提示
除了顯示輸出外,也可以在執行指令的過程中詢問使用者來提供輸入。ask
方法會提示使用者給定的問題,並接受使用者輸入,然後將使用者的輸入回傳至指令:
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 $name = $this->ask('What is your name?');9}
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 $name = $this->ask('What is your name?');9}
secret
方法與 ask
類似,但使用者在指令列輸入的過程中將看不到他們自己的輸入值。這個方法適用於像使用者詢問如密碼等機密資訊的時候:
1$password = $this->secret('What is the password?');
1$password = $this->secret('What is the password?');
要求確認
若需要使用者回答簡單的「yes / no」的確認問題,可以使用 confirm
方法。預設情況下,這個方法會回傳 false
,但若使用者在提示時輸入 y
或 yes
,則該方法會回傳 true
。
1if ($this->confirm('Do you wish to continue?')) {2 //3}
1if ($this->confirm('Do you wish to continue?')) {2 //3}
若有必要,也可以通過將 true
傳入為 confirm
方法的第二個引數來指定讓確認提示預設回傳 true
:
1if ($this->confirm('Do you wish to continue?', true)) {2 //3}
1if ($this->confirm('Do you wish to continue?', true)) {2 //3}
自動補全
anticipate
方法可以用來為可能的選項提供自動補全。不論自動補全提示了什麼,使用者一樣可以提供任意回答:
1$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);
1$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);
另外,也可以將一個閉包傳給 anticipate
方法的第二個引數。這個閉包會在每次使用者輸入字元的時候被呼叫。該閉包應接受一個字串參數,其中包含了目前使用者的輸入值,並回傳用於自動補全的選項陣列:
1$name = $this->anticipate('What is your address?', function ($input) {2 // Return auto-completion options...3});
1$name = $this->anticipate('What is your address?', function ($input) {2 // Return auto-completion options...3});
多重選擇問題
若需要在詢問問題時為提供使用者一組預先定義的選項,可以使用 choice
方法。也可以通過將預設選項的陣列索引傳給該方法的第三個參數,來指定沒有選擇任何選項時要回傳的預設值:
1$name = $this->choice(2 'What is your name?',3 ['Taylor', 'Dayle'],4 $defaultIndex5);
1$name = $this->choice(2 'What is your name?',3 ['Taylor', 'Dayle'],4 $defaultIndex5);
另外,choice
方法也接受第 4 個與第 5 個引數,這兩個引數分別是用來判斷選擇有效回答的最大嘗試次數,以及是否允許多重選擇:
1$name = $this->choice(2 'What is your name?',3 ['Taylor', 'Dayle'],4 $defaultIndex,5 $maxAttempts = null,6 $allowMultipleSelections = false7);
1$name = $this->choice(2 'What is your name?',3 ['Taylor', 'Dayle'],4 $defaultIndex,5 $maxAttempts = null,6 $allowMultipleSelections = false7);
撰寫輸出
若要將輸出傳送至主控台,可以使用 line
, info
, comment
, question
, warn
與 error
方法。這幾個方法會依不同目的來使用適當的 ANSI 色彩。舉例來說,我們來顯示一些一般的資訊給使用者看。通常來說,info
方法會在主控台上顯示出綠色的文字:
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 // ...910 $this->info('The command was successful!');11}
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 // ...910 $this->info('The command was successful!');11}
若要顯示錯誤訊息,可以使用 error
方法。錯誤訊息文字通常會以紅色顯示:
1$this->error('Something went wrong!');
1$this->error('Something went wrong!');
也可以使用 line
方法來顯示未標示色彩的純文字:
1$this->line('Display this on the screen');
1$this->line('Display this on the screen');
可以使用 newLine
方法來顯示空行:
1// Write a single blank line...2$this->newLine();34// Write three blank lines...5$this->newLine(3);
1// Write a single blank line...2$this->newLine();34// Write three blank lines...5$this->newLine(3);
表格
The table
method makes it easy to correctly format multiple rows / columns of data. All you need to do is provide the column names and the data for the table and Laravel will
automatically calculate the appropriate width and height of the table for you:
1use App\Models\User;23$this->table(4 ['Name', 'Email'],5 User::all(['name', 'email'])->toArray()6);
1use App\Models\User;23$this->table(4 ['Name', 'Email'],5 User::all(['name', 'email'])->toArray()6);
進度列
當有需要長時間執行的任務時,最好顯示一個能告訴使用者目前任務完成度的進度列。使用 withProgressBar
方法,Laravel 就會顯示出一個進度列,並在每次迭代過指定的迭代值時增加進度列的進度:
1use App\Models\User;23$users = $this->withProgressBar(User::all(), function ($user) {4 $this->performTask($user);5});
1use App\Models\User;23$users = $this->withProgressBar(User::all(), function ($user) {4 $this->performTask($user);5});
有時候,我們可能需要手動控制進度列何時需要增加。首先,我們先定義整個過程所需要迭代的次數。接著,在每個項目處理完後增加進度:
1$users = App\Models\User::all();23$bar = $this->output->createProgressBar(count($users));45$bar->start();67foreach ($users as $user) {8 $this->performTask($user);910 $bar->advance();11}1213$bar->finish();
1$users = App\Models\User::all();23$bar = $this->output->createProgressBar(count($users));45$bar->start();67foreach ($users as $user) {8 $this->performTask($user);910 $bar->advance();11}1213$bar->finish();
有關更進階的選項,請參考 Symfony Progress Bar 元件說明文件。
註冊指令
所有主控台指令都在 App\Console\Kernel
類別內自動註冊。該類別為專案的「主控台核心」。在該類別的 commands
方法內,可以看到一個核心 load
方法的呼叫。load
方法會掃描 app/Console/Commands
目錄並自動向 Artisan 註冊其中的各個指令。你也可以在 load
方法中加上額外的呼叫來掃描其他目錄中的 Artisan 指令:
1/**2 * Register the commands for the application.3 *4 * @return void5 */6protected function commands()7{8 $this->load(__DIR__.'/Commands');9 $this->load(__DIR__.'/../Domain/Orders/Commands');1011 // ...12}
1/**2 * Register the commands for the application.3 *4 * @return void5 */6protected function commands()7{8 $this->load(__DIR__.'/Commands');9 $this->load(__DIR__.'/../Domain/Orders/Commands');1011 // ...12}
若有需要的話,也可以通過將指令的類別名稱加至 App\Console\Kernel
類別的 $commands
屬性來手動註冊指令。若該屬性不存在,你可以手動建立。當 Artisan 啟動時,列在該屬性上的所有指令都會由 Service Container 進行解析,並向 Artisan 註冊:
1protected $commands = [2 Commands\SendEmails::class3];
1protected $commands = [2 Commands\SendEmails::class3];
通過程式碼執行指令
有時候可能需要在 CLI 以外的地方執行 Artisan 指令。舉例來說,你可能會想在路由或控制器內執行 Artisan 指令。可以使用 Artisan
Facade 的 call
方法來完成這一目標。可以傳入指令的簽章名稱或類別名稱給 call
方法的第一個引數,而指令的參數則可以陣列傳為第二個引數。指令的結束代碼(Exit Code)會被回傳:
1use Illuminate\Support\Facades\Artisan;23Route::post('/user/{user}/mail', function ($user) {4 $exitCode = Artisan::call('mail:send', [5 'user' => $user, '--queue' => 'default'6 ]);78 //9});
1use Illuminate\Support\Facades\Artisan;23Route::post('/user/{user}/mail', function ($user) {4 $exitCode = Artisan::call('mail:send', [5 'user' => $user, '--queue' => 'default'6 ]);78 //9});
或者,也可以將整個 Artisan 指令作為字串傳給 call
方法:
1Artisan::call('mail:send 1 --queue=default');
1Artisan::call('mail:send 1 --queue=default');
傳入陣列值
若指令有定義接受陣列的選項,則可將陣列傳給該選項:
1use Illuminate\Support\Facades\Artisan;23Route::post('/mail', function () {4 $exitCode = Artisan::call('mail:send', [5 '--id' => [5, 13]6 ]);7});
1use Illuminate\Support\Facades\Artisan;23Route::post('/mail', function () {4 $exitCode = Artisan::call('mail:send', [5 '--id' => [5, 13]6 ]);7});
傳入布林值
若有需要為不接受字串值的選項指定值,如 migrate:refresh
指令的 --force
旗標,則可以為該選項傳入 true
或 false
:
1$exitCode = Artisan::call('migrate:refresh', [2 '--force' => true,3]);
1$exitCode = Artisan::call('migrate:refresh', [2 '--force' => true,3]);
將 Artisan 指令放入佇列
只需要使用 Artisan
Facade 的 queue
方法,就可以將 Artisan 指令放入佇列執行,這樣這個指令就會在 佇列背景工作角色 內背景執行。在使用該方法前,請先確認是否已設定好佇列,且有執行佇列監聽程式:
1use Illuminate\Support\Facades\Artisan;23Route::post('/user/{user}/mail', function ($user) {4 Artisan::queue('mail:send', [5 'user' => $user, '--queue' => 'default'6 ]);78 //9});
1use Illuminate\Support\Facades\Artisan;23Route::post('/user/{user}/mail', function ($user) {4 Artisan::queue('mail:send', [5 'user' => $user, '--queue' => 'default'6 ]);78 //9});
可以使用 onConnection
與 onQueue
方法來指定 Artisan 指令應分派到哪個連線或佇列上:
1Artisan::queue('mail:send', [2 'user' => 1, '--queue' => 'default'3])->onConnection('redis')->onQueue('commands');
1Artisan::queue('mail:send', [2 'user' => 1, '--queue' => 'default'3])->onConnection('redis')->onQueue('commands');
在其他指令內執行指令
有時候可能需要在現有 Artisan 指令內執行另一個指令。可以通過呼叫 call
方法來完成。call
方法接受指令名稱與指令的引數與選項:
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 $this->call('mail:send', [9 'user' => 1, '--queue' => 'default'10 ]);1112 //13}
1/**2 * Execute the console command.3 *4 * @return mixed5 */6public function handle()7{8 $this->call('mail:send', [9 'user' => 1, '--queue' => 'default'10 ]);1112 //13}
若有需要呼叫另一個主控台指令並忽略其所有輸出,則可使用 callSilently
方法。callSilently
方法的簽章與 call
方法相同:
1$this->callSilently('mail:send', [2 'user' => 1, '--queue' => 'default'3]);
1$this->callSilently('mail:send', [2 'user' => 1, '--queue' => 'default'3]);
處理訊號
驅動 Artisan 主控台的 Symfony Console 能夠設定指令能處理那些處理程序訊號(若有的話)。舉例來說,你可能會想要讓指令能處理 SIGINT
與 SIGTERM
訊號。
要開始處理訊號,請先在 Artisan 指令類別上實作 Symfony\Component\Console\Command\SignalableCommandInterface
介面。這個介面要求要定義兩個方法:getSubscribedSignals
與 handleSignal
:
1<?php23use Symfony\Component\Console\Command\SignalableCommandInterface;45class StartServer extends Command implements SignalableCommandInterface6{7 // ...89 /**10 * Get the list of signals handled by the command.11 *12 * @return array13 */14 public function getSubscribedSignals(): array15 {16 return [SIGINT, SIGTERM];17 }1819 /**20 * Handle an incoming signal.21 *22 * @param int $signal23 * @return void24 */25 public function handleSignal(int $signal): void26 {27 if ($signal === SIGINT) {28 $this->stopServer();2930 return;31 }32 }33}
1<?php23use Symfony\Component\Console\Command\SignalableCommandInterface;45class StartServer extends Command implements SignalableCommandInterface6{7 // ...89 /**10 * Get the list of signals handled by the command.11 *12 * @return array13 */14 public function getSubscribedSignals(): array15 {16 return [SIGINT, SIGTERM];17 }1819 /**20 * Handle an incoming signal.21 *22 * @param int $signal23 * @return void24 */25 public function handleSignal(int $signal): void26 {27 if ($signal === SIGINT) {28 $this->stopServer();2930 return;31 }32 }33}
你可能已經看得出來,getSubscribedSignals
應回傳一個包含所有指令能處理訊號的陣列,而 handleSignal
則接收訊號並根據訊號進行回應。
自訂 Stub
Artisan 主控台的 make
指令可以用來建立各種類別,如控制器、任務、資料庫遷移,以及測試。這些類別都是使用「Stub (虛設常式)」來產生的,Stub 會依據給定的輸入來填入不同的值。不過,你可能會想對這些 Artisan 產生的檔案做一些微調。要修改這些 Stub,可以通過 stub:publish
指令來將這些最常見的 Stub 安裝到專案中,如此一來就能自訂這些 Stub:
1php artisan stub:publish
1php artisan stub:publish
安裝的 Stub 會被放在專案根目錄的 stubs
目錄中。對這些 Stub 做出的任何改動都會反應到使用 Artisan 的 make
指令所產生的對應類別上。
事件
Artisan 會在執行指令的時候分派三個事件: Illuminate\Console\Events\ArtisanStarting
, Illuminate\Console\Events\CommandStarting
與 Illuminate\Console\Events\CommandFinished
。ArtisanStarting
事件會在 Artisan 開始執行後馬上被分派。接著,CommandStarting
事件會在指令開始執行前的瞬間被分派。最後,CommandFinished
事件會在指令完成執行後被分派。