翻譯進度
47.22% 已翻譯
更新時間:
2024年6月30日 上午8:17:00 [世界標準時間]
翻譯人員:
幫我們翻譯此頁

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./vendor/bin/sail artisan list
1./vendor/bin/sail artisan list

Tinker (REPL)

Laravel Tinker 是用於 Laravel 框架的強大 REPL,由 PsySH 套件提供。

安裝

所有的 Laravel 專案預設都包含了 Tinker。但若先前曾自專案內移除 Tinker,則可使用 Composer 來安裝:

1composer require laravel/tinker
1composer require laravel/tinker
lightbulb

Looking for hot reloading, multiline code editing, and autocompletion when interacting with your Laravel application? Check out 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"
lightbulb

dispatch 輔助函式與 Dispatchable 類別上的 dispatch 方法需要仰賴垃圾回收機制來將任務放進佇列中。因此,在使用 Tinker 時,應使用 Bus::dispatchQueue::push 來分派任務。

指令允許列表

Tinker utilizes an "allow" list to determine which Artisan commands are allowed to be run within its shell. By default, you may run the clear-compiled, down, env, inspire, migrate, migrate:install, up, and optimize commands. If you would like to allow more commands you may add them to the commands array in your tinker.php configuration file:

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

指令結構

產生指令後,應為類別的 signaturedescription 屬性定義適當的值。當在 list 畫面內顯示該指令時,就會用到這些屬性。signature 屬性可以用來定義 指令預期的輸入handle 方法會在執行該指令時呼叫。可以將指令的邏輯放在該方法內。

來看看一個範例指令。請注意,我們可以通過指令的 handle 方法來要求任意的相依性。Laravel 的 Service Container 會自動插入所有在方法簽章內有型別提示的相依性。

1<?php
2 
3namespace App\Console\Commands;
4 
5use App\Models\User;
6use App\Support\DripEmailer;
7use Illuminate\Console\Command;
8 
9class SendEmails extends Command
10{
11 /**
12 * The name and signature of the console command.
13 *
14 * @var string
15 */
16 protected $signature = 'mail:send {user}';
17 
18 /**
19 * The console command description.
20 *
21 * @var string
22 */
23 protected $description = 'Send a marketing email to a user';
24 
25 /**
26 * Execute the console command.
27 */
28 public function handle(DripEmailer $drip): void
29 {
30 $drip->send(User::find($this->argument('user')));
31 }
32}
1<?php
2 
3namespace App\Console\Commands;
4 
5use App\Models\User;
6use App\Support\DripEmailer;
7use Illuminate\Console\Command;
8 
9class SendEmails extends Command
10{
11 /**
12 * The name and signature of the console command.
13 *
14 * @var string
15 */
16 protected $signature = 'mail:send {user}';
17 
18 /**
19 * The console command description.
20 *
21 * @var string
22 */
23 protected $description = 'Send a marketing email to a user';
24 
25 /**
26 * Execute the console command.
27 */
28 public function handle(DripEmailer $drip): void
29 {
30 $drip->send(User::find($this->argument('user')));
31 }
32}
lightbulb

為了提升程式碼重複使用率,最好保持主控台指令精簡,並將指令的任務委託給應用程式服務來完成。在上方的例子中,可以注意到我們插入了一個服務類別來處理寄送 E-Mail 的這個「重責大任」。

Exit Codes

If nothing is returned from the handle method and the command executes successfully, the command will exit with a 0 exit code, indicating success. However, the handle method may optionally return an integer to manually specify command's exit code:

1$this->error('Something went wrong.');
2 
3return 1;
1$this->error('Something went wrong.');
2 
3return 1;

If you would like to "fail" the command from any method within the command, you may utilize the fail method. The fail method will immediately terminate execution of the command and return an exit code of 1:

1$this->fail('Something went wrong.');
1$this->fail('Something went wrong.');

閉包指令

Closure based commands provide an alternative to defining console commands as classes. In the same way that route closures are an alternative to controllers, think of command closures as an alternative to command classes.

Even though the routes/console.php file does not define HTTP routes, it defines console based entry points (routes) into your application. Within this file, you may define all of your closure based console commands using the Artisan::command method. The command method accepts two arguments: the command signature and a closure which receives the command's arguments and options:

1Artisan::command('mail:send {user}', function (string $user) {
2 $this->info("Sending email to: {$user}!");
3});
1Artisan::command('mail:send {user}', function (string $user) {
2 $this->info("Sending email to: {$user}!");
3});

這裡的閉包有綁定到該指令的基礎類別執行個體,因此可以像在完整的指令類別內一樣存取所有的輔助函式。

對相依關係進行型別提示

除了接收指令的引數與選項外,指令閉包也可以通過型別提示來向 Service Container 解析額外的相依關係。

1use App\Models\User;
2use App\Support\DripEmailer;
3 
4Artisan::command('mail:send {user}', function (DripEmailer $drip, string $user) {
5 $drip->send(User::find($user));
6});
1use App\Models\User;
2use App\Support\DripEmailer;
3 
4Artisan::command('mail:send {user}', function (DripEmailer $drip, string $user) {
5 $drip->send(User::find($user));
6});

閉包指令描述

在定義基於閉包的指令時,可以使用 purpose 方法來為該指令加上描述。這段描述會在執行 php artisan listphp artisan help 指令時顯示:

1Artisan::command('mail:send {user}', function (string $user) {
2 // ...
3})->purpose('Send a marketing email to a user');
1Artisan::command('mail:send {user}', function (string $user) {
2 // ...
3})->purpose('Send a marketing email to a user');

可隔離的指令

lightbulb

若要使用此功能,則應用程式必須要使用 memcached, redis, dynamodb, database, filearray 作為應用程式的預設快取 Driver。另外,所有的伺服器也都必須要連線至相同的中央快取伺服器。

有時候,我們可能需要確保某個指令在同一時間只有一個實體在執行。為此,可以在指令類別上實作 Illuminate\Contracts\Console\Isolatable Interface:

1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6use Illuminate\Contracts\Console\Isolatable;
7 
8class SendEmails extends Command implements Isolatable
9{
10 // ...
11}
1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6use Illuminate\Contracts\Console\Isolatable;
7 
8class SendEmails extends Command implements Isolatable
9{
10 // ...
11}

將指令標記為 `Isolatable`(可隔離的) 後,Laravel 會自動為該指令加上一個 --isolated 選項。使用 --isolated 選項呼叫該指令時,Laravel 會確保沒有其他該指令的實體正在執行。Laravel 通過在預設快取 Driver 上取得 Atomic Lock(不可部分完成鎖定) 來確保只有一個實體在執行。若該指令有其他實體在執行,就不會執行該指令。不過,該指令依然會以成功的終止狀態碼結束:

1php artisan mail:send 1 --isolated
1php artisan mail:send 1 --isolated

若想指定該指令無法執行時回傳的終止狀態碼,可使用 isolated 選項來設定:

1php artisan mail:send 1 --isolated=12
1php artisan mail:send 1 --isolated=12

Lock ID

預設情況下,Laravel 會使用該指令的名稱來產生一組字串索引鍵,以用在專案快取中取得 Atomic Lock。不過,只要在 Artisan Command 類別上定義 isolatebleId 方法,就可以自定這個索引鍵,讓你能將該指令的引數或選項整合進索引鍵中:

1/**
2 * Get the isolatable ID for the command.
3 */
4public function isolatableId(): string
5{
6 return $this->argument('user');
7}
1/**
2 * Get the isolatable ID for the command.
3 */
4public function isolatableId(): string
5{
6 return $this->argument('user');
7}

Lock 的逾期時間

預設情況下,指令完成執行後,獨立指令的 Lock 就會逾時。而如果指令在執行時遭到中斷而無法完成,該 Lock 會在一小時後逾時。不過,你可以在指令中定義一個 isolationLockExpiresAt 方法來調整逾時時間:

1use DateTimeInterface;
2use DateInterval;
3 
4/**
5 * Determine when an isolation lock expires for the command.
6 */
7public function isolationLockExpiresAt(): DateTimeInterface|DateInterval
8{
9 return now()->addMinutes(5);
10}
1use DateTimeInterface;
2use DateInterval;
3 
4/**
5 * Determine when an isolation lock expires for the command.
6 */
7public function isolationLockExpiresAt(): DateTimeInterface|DateInterval
8{
9 return now()->addMinutes(5);
10}

定義預期的輸入

在撰寫主控台指令時,常常會通過引數或選項來向使用者取得輸入。Laravel 通過指令的 signature 屬性來定義預期從使用者那取得的輸入,讓這個過程變得非常簡單。通過 signature 屬性,就能通過類似路由的格式來一次定義名稱、引數,以及選項。非常簡潔有力。

引數

所有由使用者提供的引數與選項都以大括號來包裝。在下列範例中的指令定義了一個必要的引數:user

1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
6protected $signature = 'mail:send {user}';
1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
6protected $signature = 'mail:send {user}';

也可以將引數設為可選,或是定義引數的預設值:

1// Optional argument...
2'mail:send {user?}'
3 
4// Optional argument with default value...
5'mail:send {user=foo}'
1// Optional argument...
2'mail:send {user?}'
3 
4// Optional argument with default value...
5'mail:send {user=foo}'

選項

選項就像引數一樣,是另一種形式的使用者輸入。選項在從指令列提供時,會加上兩個減號 (--) 作為前綴。有兩種類型的選項:一種可接收值,一種沒有接收值。沒有接收值的選項是一種布林「開關」功能。來看看一個使用這種類型選項的例子:

1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
6protected $signature = 'mail:send {user} {--queue}';
1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
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 string
5 */
6protected $signature = 'mail:send {user} {--queue=}';
1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
6protected $signature = 'mail:send {user} {--queue=}';

在這個例子中,使用者可以傳入像這樣給選項帶入一個值。若在叫用該指令時未指定該選項,則其值為 null

1php artisan mail:send 1 --queue=default
1php artisan mail:send 1 --queue=default

可以通過在選項名稱後方加上預設值來為選項指派一個預設值。若使用者未傳入選項值,將會使用預設值:

1'mail:send {user} {--queue=default}'
1'mail:send {user} {--queue=default}'

選項捷徑

若要在定義選項時指定捷徑,可以在選項名稱前加上其捷徑名稱,並使用 | 字元來區分捷徑名稱與完整的選項名稱:

1'mail:send {user} {--Q|queue}'
1'mail:send {user} {--Q|queue}'

在終端機中呼叫指令時,選項捷徑前面應該只有一個減號,且在指定選項值時不應加上 = 字元:

1php artisan mail:send 1 -Qdefault
1php artisan mail:send 1 -Qdefault

輸入陣列

若想要定義預期有多個輸入值的引數或選項,則可以使用 * 字元。首先,來看看這樣設定引數的例子:

1'mail:send {user*}'
1'mail:send {user*}'

呼叫這個方法的時候,user 引數在指令列中可以按照順序傳入。舉例來說,下列指令會將 user 的值設為一個內容為 12 的陣列:

1php artisan mail:send 1 2
1php artisan mail:send 1 2

* 字元可以與可選引數組合使用來定義,這樣一來可允許有 0 個或多個引數的實體:

1'mail:send {user?*}'
1'mail:send {user?*}'

選項陣列

定義預期有多個輸入值的選項時,每個傳入指令的選項值都應以選項名稱作為前綴:

1'mail:send {--id=*}'
1'mail:send {--id=*}'

可以通過傳入多個 -id 引數來叫用這樣的指令:

1php artisan mail:send --id=1 --id=2
1php artisan mail:send --id=1 --id=2

輸入描述

可以通過以冒號 (:) 區分引數名與描述來為輸入引數或選項指定描述。若需要更多空間來定義指令的話,可以將定義拆分為多行:

1/**
2 * The name and signature of the console command.
3 *
4 * @var string
5 */
6protected $signature = 'mail:send
7 {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 string
5 */
6protected $signature = 'mail:send
7 {user : The ID of the user}
8 {--queue : Whether the job should be queued}';

Prompting for Missing Input

當指令有包含必填的引數時,若使用者未提供這些引數,則會產生錯誤訊息。除了產生錯誤訊息外,只要實作 PromptsForMissingInput Interface(介面),就可以讓 Command 在使用者未提供必填引數時自動提示使用者輸入。

1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6use Illuminate\Contracts\Console\PromptsForMissingInput;
7 
8class SendEmails extends Command implements PromptsForMissingInput
9{
10 /**
11 * The name and signature of the console command.
12 *
13 * @var string
14 */
15 protected $signature = 'mail:send {user}';
16 
17 // ...
18}
1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6use Illuminate\Contracts\Console\PromptsForMissingInput;
7 
8class SendEmails extends Command implements PromptsForMissingInput
9{
10 /**
11 * The name and signature of the console command.
12 *
13 * @var string
14 */
15 protected $signature = 'mail:send {user}';
16 
17 // ...
18}

當 Laravel 需要從使用者取得必填引數時,Laravel 會自動智慧地使用引數名稱與說明來產生提問,並向使用者要求輸入。若想自定必填引數的提問,可實作 promptForMissingArgumentsUsing 方法,並回傳一組以引數名稱為索引鍵的問題陣列:

1/**
2 * Prompt for missing input arguments using the returned questions.
3 *
4 * @return array<string, string>
5 */
6protected function promptForMissingArgumentsUsing(): array
7{
8 return [
9 'user' => 'Which user ID should receive the mail?',
10 ];
11}
1/**
2 * Prompt for missing input arguments using the returned questions.
3 *
4 * @return array<string, string>
5 */
6protected function promptForMissingArgumentsUsing(): array
7{
8 return [
9 'user' => 'Which user ID should receive the mail?',
10 ];
11}

也可以使用包含提問與預留位置 (Placeholder) 的 Tuple(有序元素) 來提供預留位置文字:

1return [
2 'user' => ['Which user ID should receive the mail?', 'E.g. 123'],
3];
1return [
2 'user' => ['Which user ID should receive the mail?', 'E.g. 123'],
3];

若想完全控制提示,可以提供一個 Closure 以用於向使用者提問並回傳使用者提供的答案:

1use App\Models\User;
2use function Laravel\Prompts\search;
3 
4// ...
5 
6return [
7 'user' => fn () => search(
8 label: 'Search for a user:',
9 placeholder: 'E.g. Taylor Otwell',
10 options: fn ($value) => strlen($value) > 0
11 ? User::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
12 : []
13 ),
14];
1use App\Models\User;
2use function Laravel\Prompts\search;
3 
4// ...
5 
6return [
7 'user' => fn () => search(
8 label: 'Search for a user:',
9 placeholder: 'E.g. Taylor Otwell',
10 options: fn ($value) => strlen($value) > 0
11 ? User::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
12 : []
13 ),
14];
lightbulb

完整的 Laravel Prompts 說明文件中包含了有關可用的提示及其使用方法的更多資訊。

若想提示使用者選擇或輸入選項,則可在 Command 的 handle 方法中包含提示。不過,若只想在使用者同時被提示未提供的引數時提示使用者,則可實作 afterPromptingForMissingArguments 方法:

1use Symfony\Component\Console\Input\InputInterface;
2use Symfony\Component\Console\Output\OutputInterface;
3use function Laravel\Prompts\confirm;
4 
5// ...
6 
7/**
8 * Perform actions after the user was prompted for missing arguments.
9 */
10protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void
11{
12 $input->setOption('queue', confirm(
13 label: 'Would you like to queue the mail?',
14 default: $this->option('queue')
15 ));
16}
1use Symfony\Component\Console\Input\InputInterface;
2use Symfony\Component\Console\Output\OutputInterface;
3use function Laravel\Prompts\confirm;
4 
5// ...
6 
7/**
8 * Perform actions after the user was prompted for missing arguments.
9 */
10protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void
11{
12 $input->setOption('queue', confirm(
13 label: 'Would you like to queue the mail?',
14 default: $this->option('queue')
15 ));
16}

指令 I/O

截取輸入

指令執行時,我們通常需要存取這些指令所接收的引數與選項值。要截取這些值,可以使用 argumentoption 方法。若引數或選項不存在,則會回傳 null

1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $userId = $this->argument('user');
7}
1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $userId = $this->argument('user');
7}

若要將所有引數截取為陣列,則可呼叫 arguments 方法:

1$arguments = $this->arguments();
1$arguments = $this->arguments();

我們也可像截取引數一樣使用 option 方法來輕鬆地截取選項。若要將所有選項截取為陣列,請呼叫 options 方法:

1// Retrieve a specific option...
2$queueName = $this->option('queue');
3 
4// Retrieve all options as an array...
5$options = $this->options();
1// Retrieve a specific option...
2$queueName = $this->option('queue');
3 
4// Retrieve all options as an array...
5$options = $this->options();

Prompting for Input

lightbulb

Laravel Prompts 是一個 PHP 套件,可用來在 CLI 應用程式中新增好看且對使用者友善的表單,並具有類似瀏覽器中的功能,如預留位置文字與表單驗證。

除了顯示輸出外,也可以在執行指令的過程中詢問使用者來提供輸入。ask 方法會提示使用者給定的問題,並接受使用者輸入,然後將使用者的輸入回傳至指令:

1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $name = $this->ask('What is your name?');
7 
8 // ...
9}
1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $name = $this->ask('What is your name?');
7 
8 // ...
9}

The ask method also accepts an optional second argument which specifies the default value that should be returned if no user input is provided:

1$name = $this->ask('What is your name?', 'Taylor');
1$name = $this->ask('What is your name?', 'Taylor');

secret 方法與 ask 類似,但使用者在指令列輸入的過程中將看不到他們自己的輸入值。這個方法適用於像使用者詢問如密碼等機密資訊的時候:

1$password = $this->secret('What is the password?');
1$password = $this->secret('What is the password?');

Asking for Confirmation

若需要使用者回答簡單的「yes / no」的確認問題,可以使用 confirm 方法。預設情況下,這個方法會回傳 false,但若使用者在提示時輸入 yyes,則該方法會回傳 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 (string $input) {
2 // Return auto-completion options...
3});
1$name = $this->anticipate('What is your address?', function (string $input) {
2 // Return auto-completion options...
3});

多重選擇問題

若需要在詢問問題時為提供使用者一組預先定義的選項,可以使用 choice 方法。也可以通過將預設選項的陣列索引傳給該方法的第三個參數,來指定沒有選擇任何選項時要回傳的預設值:

1$name = $this->choice(
2 'What is your name?',
3 ['Taylor', 'Dayle'],
4 $defaultIndex
5);
1$name = $this->choice(
2 'What is your name?',
3 ['Taylor', 'Dayle'],
4 $defaultIndex
5);

另外,choice 方法也接受第 4 個與第 5 個引數,這兩個引數分別是用來判斷選擇有效回答的最大嘗試次數,以及是否允許多重選擇:

1$name = $this->choice(
2 'What is your name?',
3 ['Taylor', 'Dayle'],
4 $defaultIndex,
5 $maxAttempts = null,
6 $allowMultipleSelections = false
7);
1$name = $this->choice(
2 'What is your name?',
3 ['Taylor', 'Dayle'],
4 $defaultIndex,
5 $maxAttempts = null,
6 $allowMultipleSelections = false
7);

撰寫輸出

若要將輸出傳送至主控台,可以使用 line, info, comment, question, warnerror 方法。這幾個方法會依不同目的來使用適當的 ANSI 色彩。舉例來說,我們來顯示一些一般的資訊給使用者看。通常來說,info 方法會在主控台上顯示出綠色的文字:

1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 // ...
7 
8 $this->info('The command was successful!');
9}
1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 // ...
7 
8 $this->info('The command was successful!');
9}

若要顯示錯誤訊息,可以使用 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();
3 
4// Write three blank lines...
5$this->newLine(3);
1// Write a single blank line...
2$this->newLine();
3 
4// 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;
2 
3$this->table(
4 ['Name', 'Email'],
5 User::all(['name', 'email'])->toArray()
6);
1use App\Models\User;
2 
3$this->table(
4 ['Name', 'Email'],
5 User::all(['name', 'email'])->toArray()
6);

進度列

當有需要長時間執行的任務時,最好顯示一個能告訴使用者目前任務完成度的進度列。使用 withProgressBar 方法,Laravel 就會顯示出一個進度列,並在每次迭代過指定的迭代值時增加進度列的進度:

1use App\Models\User;
2 
3$users = $this->withProgressBar(User::all(), function (User $user) {
4 $this->performTask($user);
5});
1use App\Models\User;
2 
3$users = $this->withProgressBar(User::all(), function (User $user) {
4 $this->performTask($user);
5});

有時候,我們可能需要手動控制進度列何時需要增加。首先,我們先定義整個過程所需要迭代的次數。接著,在每個項目處理完後增加進度:

1$users = App\Models\User::all();
2 
3$bar = $this->output->createProgressBar(count($users));
4 
5$bar->start();
6 
7foreach ($users as $user) {
8 $this->performTask($user);
9 
10 $bar->advance();
11}
12 
13$bar->finish();
1$users = App\Models\User::all();
2 
3$bar = $this->output->createProgressBar(count($users));
4 
5$bar->start();
6 
7foreach ($users as $user) {
8 $this->performTask($user);
9 
10 $bar->advance();
11}
12 
13$bar->finish();
lightbulb

For more advanced options, check out the Symfony Progress Bar component documentation.

註冊指令

By default, Laravel automatically registers all commands within the app/Console/Commands directory. However, you can instruct Laravel to scan other directories for Artisan commands using the withCommands method in your application's bootstrap/app.php file:

1->withCommands([
2 __DIR__.'/../app/Domain/Orders/Commands',
3])
1->withCommands([
2 __DIR__.'/../app/Domain/Orders/Commands',
3])

If necessary, you may also manually register commands by providing the command's class name to the withCommands method:

1use App\Domain\Orders\Commands\SendEmails;
2 
3->withCommands([
4 SendEmails::class,
5])
1use App\Domain\Orders\Commands\SendEmails;
2 
3->withCommands([
4 SendEmails::class,
5])

When Artisan boots, all the commands in your application will be resolved by the service container and registered with Artisan.

通過程式碼執行指令

有時候可能需要在 CLI 以外的地方執行 Artisan 指令。舉例來說,你可能會想在路由或控制器內執行 Artisan 指令。可以使用 Artisan Facade 的 call 方法來完成這一目標。可以傳入指令的簽章名稱或類別名稱給 call 方法的第一個引數,而指令的參數則可以陣列傳為第二個引數。指令的結束代碼(Exit Code)會被回傳:

1use Illuminate\Support\Facades\Artisan;
2 
3Route::post('/user/{user}/mail', function (string $user) {
4 $exitCode = Artisan::call('mail:send', [
5 'user' => $user, '--queue' => 'default'
6 ]);
7 
8 // ...
9});
1use Illuminate\Support\Facades\Artisan;
2 
3Route::post('/user/{user}/mail', function (string $user) {
4 $exitCode = Artisan::call('mail:send', [
5 'user' => $user, '--queue' => 'default'
6 ]);
7 
8 // ...
9});

或者,也可以將整個 Artisan 指令作為字串傳給 call 方法:

1Artisan::call('mail:send 1 --queue=default');
1Artisan::call('mail:send 1 --queue=default');

傳入陣列值

若指令有定義接受陣列的選項,則可將陣列傳給該選項:

1use Illuminate\Support\Facades\Artisan;
2 
3Route::post('/mail', function () {
4 $exitCode = Artisan::call('mail:send', [
5 '--id' => [5, 13]
6 ]);
7});
1use Illuminate\Support\Facades\Artisan;
2 
3Route::post('/mail', function () {
4 $exitCode = Artisan::call('mail:send', [
5 '--id' => [5, 13]
6 ]);
7});

傳入布林值

若有需要為不接受字串值的選項指定值,如 migrate:refresh 指令的 --force 旗標,則可以為該選項傳入 truefalse

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;
2 
3Route::post('/user/{user}/mail', function (string $user) {
4 Artisan::queue('mail:send', [
5 'user' => $user, '--queue' => 'default'
6 ]);
7 
8 // ...
9});
1use Illuminate\Support\Facades\Artisan;
2 
3Route::post('/user/{user}/mail', function (string $user) {
4 Artisan::queue('mail:send', [
5 'user' => $user, '--queue' => 'default'
6 ]);
7 
8 // ...
9});

可以使用 onConnectiononQueue 方法來指定 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 */
4public function handle(): void
5{
6 $this->call('mail:send', [
7 'user' => 1, '--queue' => 'default'
8 ]);
9 
10 // ...
11}
1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $this->call('mail:send', [
7 'user' => 1, '--queue' => 'default'
8 ]);
9 
10 // ...
11}

若有需要呼叫另一個主控台指令並忽略其所有輸出,則可使用 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]);

處理訊號

讀者可能已經知道,在作業系統中,我們可以傳送訊號 (Signal) 給正在執行的處理程序。舉例來說,作業系統會使用 SIGTERM 訊號來要求某個程式停止執行。若想在 Artisan 主控台指令上監聽這些訊號,可使用 trap 方法:

1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $this->trap(SIGTERM, fn () => $this->shouldKeepRunning = false);
7 
8 while ($this->shouldKeepRunning) {
9 // ...
10 }
11}
1/**
2 * Execute the console command.
3 */
4public function handle(): void
5{
6 $this->trap(SIGTERM, fn () => $this->shouldKeepRunning = false);
7 
8 while ($this->shouldKeepRunning) {
9 // ...
10 }
11}

若要同時監聽多個訊號,可提供一組訊號的陣列給 trap 方法:

1$this->trap([SIGTERM, SIGQUIT], function (int $signal) {
2 $this->shouldKeepRunning = false;
3 
4 dump($signal); // SIGTERM / SIGQUIT
5});
1$this->trap([SIGTERM, SIGQUIT], function (int $signal) {
2 $this->shouldKeepRunning = false;
3 
4 dump($signal); // SIGTERM / SIGQUIT
5});

自訂 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\CommandStartingIlluminate\Console\Events\CommandFinishedArtisanStarting 事件會在 Artisan 開始執行後馬上被分派。接著,CommandStarting 事件會在指令開始執行前的瞬間被分派。最後,CommandFinished 事件會在指令完成執行後被分派。

翻譯進度
47.22% 已翻譯
更新時間:
2024年6月30日 上午8:17:00 [世界標準時間]
翻譯人員:
幫我們翻譯此頁

留言

尚無留言

“Laravel” is a Trademark of Taylor Otwell.
The source documentation is released under MIT license. See laravel/docs on GitHub for details.
The translated documentations are released under MIT license. See cornch/laravel-docs-l10n on GitHub for details.