跳至內容

提示

簡介

Laravel Prompts 是一個 PHP 套件,用於為您的命令列應用程式新增美觀且使用者友善的表單,具有類似瀏覽器的功能,包括佔位符文字和驗證。

Laravel Prompts 非常適合在您的 Artisan 控制台命令中接受使用者輸入,但它也可以用於任何命令列 PHP 專案。

lightbulb

Laravel Prompts 支援 macOS、Linux 和 Windows(使用 WSL)。如需更多資訊,請參閱我們關於不支援的環境和後備方案的文件。

安裝

Laravel Prompts 已包含在最新版本的 Laravel 中。

Laravel Prompts 也可以使用 Composer 套件管理員安裝在您的其他 PHP 專案中

composer require laravel/prompts

可用的提示

文字

text 函數會使用給定的問題提示使用者,接受他們的輸入,然後傳回該輸入

use function Laravel\Prompts\text;
 
$name = text('What is your name?');

您也可以包含佔位符文字、預設值和資訊提示

$name = text(
label: 'What is your name?',
placeholder: 'E.g. Taylor Otwell',
default: $user?->name,
hint: 'This will be displayed on your profile.'
);

必要值

如果您要求必須輸入值,您可以傳遞 required 參數

$name = text(
label: 'What is your name?',
required: true
);

如果您想要自訂驗證訊息,您也可以傳遞字串

$name = text(
label: 'What is your name?',
required: 'Your name is required.'
);

其他驗證

最後,如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$name = text(
label: 'What is your name?',
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);

閉包將會接收已輸入的值,並且可以傳回錯誤訊息,或是在驗證通過時傳回 null

或者,您可以利用 Laravel 的驗證器的功能。若要執行此操作,請將包含屬性名稱和所需驗證規則的陣列提供給 validate 參數

$name = text(
label: 'What is your name?',
validate: ['name' => 'required|max:255|unique:users']
);

文字區域

textarea 函數會使用給定的問題提示使用者,透過多行文字區域接受他們的輸入,然後傳回該輸入

use function Laravel\Prompts\textarea;
 
$story = textarea('Tell me a story.');

您也可以包含佔位符文字、預設值和資訊提示

$story = textarea(
label: 'Tell me a story.',
placeholder: 'This is a story about...',
hint: 'This will be displayed on your profile.'
);

必要值

如果您要求必須輸入值,您可以傳遞 required 參數

$story = textarea(
label: 'Tell me a story.',
required: true
);

如果您想要自訂驗證訊息,您也可以傳遞字串

$story = textarea(
label: 'Tell me a story.',
required: 'A story is required.'
);

其他驗證

最後,如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$story = textarea(
label: 'Tell me a story.',
validate: fn (string $value) => match (true) {
strlen($value) < 250 => 'The story must be at least 250 characters.',
strlen($value) > 10000 => 'The story must not exceed 10,000 characters.',
default => null
}
);

閉包將會接收已輸入的值,並且可以傳回錯誤訊息,或是在驗證通過時傳回 null

或者,您可以利用 Laravel 的驗證器的功能。若要執行此操作,請將包含屬性名稱和所需驗證規則的陣列提供給 validate 參數

$story = textarea(
label: 'Tell me a story.',
validate: ['story' => 'required|max:10000']
);

密碼

password 函數與 text 函數類似,但在使用者在控制台中輸入時,其輸入將會被遮罩。當要求密碼等敏感資訊時,這非常有用

use function Laravel\Prompts\password;
 
$password = password('What is your password?');

您也可以包含佔位符文字和資訊提示

$password = password(
label: 'What is your password?',
placeholder: 'password',
hint: 'Minimum 8 characters.'
);

必要值

如果您要求必須輸入值,您可以傳遞 required 參數

$password = password(
label: 'What is your password?',
required: true
);

如果您想要自訂驗證訊息,您也可以傳遞字串

$password = password(
label: 'What is your password?',
required: 'The password is required.'
);

其他驗證

最後,如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$password = password(
label: 'What is your password?',
validate: fn (string $value) => match (true) {
strlen($value) < 8 => 'The password must be at least 8 characters.',
default => null
}
);

閉包將會接收已輸入的值,並且可以傳回錯誤訊息,或是在驗證通過時傳回 null

或者,您可以利用 Laravel 的驗證器的功能。若要執行此操作,請將包含屬性名稱和所需驗證規則的陣列提供給 validate 參數

$password = password(
label: 'What is your password?',
validate: ['password' => 'min:8']
);

確認

如果您需要詢問使用者「是或否」的確認,您可以使用 confirm 函數。使用者可以使用方向鍵或按下 yn 來選取他們的回應。此函數將會傳回 truefalse

use function Laravel\Prompts\confirm;
 
$confirmed = confirm('Do you accept the terms?');

您也可以包含預設值、自訂「是」和「否」標籤的措辭,以及資訊提示

$confirmed = confirm(
label: 'Do you accept the terms?',
default: false,
yes: 'I accept',
no: 'I decline',
hint: 'The terms must be accepted to continue.'
);

要求「是」

如有必要,您可以透過傳遞 required 參數來要求您的使用者選取「是」

$confirmed = confirm(
label: 'Do you accept the terms?',
required: true
);

如果您想要自訂驗證訊息,您也可以傳遞字串

$confirmed = confirm(
label: 'Do you accept the terms?',
required: 'You must accept the terms to continue.'
);

選擇

如果您需要使用者從預先定義的選項集合中進行選取,您可以使用 select 函數

use function Laravel\Prompts\select;
 
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner']
);

您也可以指定預設選項和資訊提示

$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner'],
default: 'Owner',
hint: 'The role may be changed at any time.'
);

您也可以將關聯陣列傳遞給 options 參數,以傳回選取的鍵,而不是其值

$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
default: 'owner'
);

在清單開始捲動之前,最多會顯示五個選項。您可以透過傳遞 scroll 參數來自訂此設定

$role = select(
label: 'Which category would you like to assign?',
options: Category::pluck('name', 'id'),
scroll: 10
);

其他驗證

與其他提示函數不同,select 函數不接受 required 參數,因為不可能不選取任何項目。但是,如果您需要呈現選項但防止選取該選項,您可以將閉包傳遞給 validate 參數

$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
validate: fn (string $value) =>
$value === 'owner' && User::where('role', 'owner')->exists()
? 'An owner already exists.'
: null
);

如果 options 參數是關聯陣列,則閉包將會接收選取的鍵,否則將會接收選取的值。閉包可能會傳回錯誤訊息,或是在驗證通過時傳回 null

多重選擇

如果您需要使用者能夠選取多個選項,您可以使用 multiselect 函數

use function Laravel\Prompts\multiselect;
 
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: ['Read', 'Create', 'Update', 'Delete']
);

您也可以指定預設選項和資訊提示

use function Laravel\Prompts\multiselect;
 
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: ['Read', 'Create', 'Update', 'Delete'],
default: ['Read', 'Create'],
hint: 'Permissions may be updated at any time.'
);

您也可以將關聯陣列傳遞給 options 參數,以傳回選取選項的鍵,而不是其值

$permissions = multiselect(
label: 'What permissions should be assigned?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
default: ['read', 'create']
);

在清單開始捲動之前,最多會顯示五個選項。您可以透過傳遞 scroll 參數來自訂此設定

$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
scroll: 10
);

要求值

依預設,使用者可以選取零個或多個選項。您可以傳遞 required 參數來強制選取一個或多個選項

$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: true
);

如果您想要自訂驗證訊息,您可以提供字串給 required 參數

$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: 'You must select at least one category'
);

其他驗證

如果您需要呈現選項但防止選取該選項,您可以將閉包傳遞給 validate 參數

$permissions = multiselect(
label: 'What permissions should the user have?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
validate: fn (array $values) => ! in_array('read', $values)
? 'All users require the read permission.'
: null
);

如果 options 參數是關聯陣列,則閉包將會接收選取的鍵,否則將會接收選取的值。閉包可能會傳回錯誤訊息,或是在驗證通過時傳回 null

建議

suggest 函數可用於為可能的選項提供自動完成功能。無論自動完成提示為何,使用者仍然可以提供任何答案

use function Laravel\Prompts\suggest;
 
$name = suggest('What is your name?', ['Taylor', 'Dayle']);

或者,您可以將閉包作為第二個參數傳遞給 suggest 函數。每次使用者輸入字元時都會呼叫該閉包。閉包應接受包含使用者目前為止輸入的字串參數,並傳回自動完成的選項陣列

$name = suggest(
label: 'What is your name?',
options: fn ($value) => collect(['Taylor', 'Dayle'])
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
)

您也可以包含佔位符文字、預設值和資訊提示

$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
placeholder: 'E.g. Taylor',
default: $user?->name,
hint: 'This will be displayed on your profile.'
);

必要值

如果您要求必須輸入值,您可以傳遞 required 參數

$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: true
);

如果您想要自訂驗證訊息,您也可以傳遞字串

$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: 'Your name is required.'
);

其他驗證

最後,如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);

閉包將會接收已輸入的值,並且可以傳回錯誤訊息,或是在驗證通過時傳回 null

或者,您可以利用 Laravel 的驗證器的功能。若要執行此操作,請將包含屬性名稱和所需驗證規則的陣列提供給 validate 參數

$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
validate: ['name' => 'required|min:3|max:255']
);

如果您有許多選項供使用者選取,search 函數允許使用者輸入搜尋查詢來篩選結果,然後使用方向鍵選取選項

use function Laravel\Prompts\search;
 
$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: []
);

閉包將會接收使用者目前為止輸入的文字,並且必須傳回選項陣列。如果您傳回關聯陣列,則將會傳回選取選項的鍵,否則將會傳回其值。

當篩選您想要傳回值的陣列時,您應該使用 array_values 函數或 values 集合方法,以確保陣列不會變成關聯陣列

$names = collect(['Taylor', 'Abigail']);
 
$selected = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => $names
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
->values()
->all(),
);

您也可以包含佔位符文字和資訊提示

$id = search(
label: 'Search for the user that should receive the mail',
placeholder: 'E.g. Taylor Otwell',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);

在清單開始捲動之前,最多會顯示五個選項。您可以透過傳遞 scroll 參數來自訂此設定

$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
scroll: 10
);

其他驗證

如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
validate: function (int|string $value) {
$user = User::findOrFail($value);
 
if ($user->opted_out) {
return 'This user has opted-out of receiving mail.';
}
}
);

如果 options 閉包傳回關聯陣列,則閉包將會接收選取的鍵,否則將會接收選取的值。閉包可能會傳回錯誤訊息,或是在驗證通過時傳回 null

多重搜尋

如果您有許多可搜尋的選項,並且需要使用者能夠選取多個項目,multisearch 函數允許使用者輸入搜尋查詢來篩選結果,然後使用方向鍵和空格鍵選取選項

use function Laravel\Prompts\multisearch;
 
$ids = multisearch(
'Search for the users that should receive the mail',
fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: []
);

閉包將會接收使用者目前為止輸入的文字,並且必須傳回選項陣列。如果您傳回關聯陣列,則將會傳回選取選項的鍵;否則,將會傳回它們的值。

當篩選您想要傳回值的陣列時,您應該使用 array_values 函數或 values 集合方法,以確保陣列不會變成關聯陣列

$names = collect(['Taylor', 'Abigail']);
 
$selected = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => $names
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
->values()
->all(),
);

您也可以包含佔位符文字和資訊提示

$ids = multisearch(
label: 'Search for the users that should receive the mail',
placeholder: 'E.g. Taylor Otwell',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);

在清單開始捲動之前,最多會顯示五個選項。您可以透過提供 scroll 參數來自訂此設定

$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
scroll: 10
);

要求值

依預設,使用者可以選取零個或多個選項。您可以傳遞 required 參數來強制選取一個或多個選項

$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
required: true
);

如果您想要自訂驗證訊息,您也可以提供字串給 required 參數

$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
required: 'You must select at least one user.'
);

其他驗證

如果您想要執行其他驗證邏輯,您可以將閉包傳遞給 validate 參數

$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
validate: function (array $values) {
$optedOut = User::whereLike('name', '%a%')->findMany($values);
 
if ($optedOut->isNotEmpty()) {
return $optedOut->pluck('name')->join(', ', ', and ').' have opted out.';
}
}
);

如果 options 閉包傳回關聯陣列,則閉包將會接收選取的鍵;否則,將會接收選取的值。閉包可能會傳回錯誤訊息,或是在驗證通過時傳回 null

暫停

pause 函數可以用於向使用者顯示資訊文字,並等待他們按下 Enter/Return 鍵來確認他們想要繼續

use function Laravel\Prompts\pause;
 
pause('Press ENTER to continue.');

驗證前轉換輸入

有時候,您可能會想要在驗證發生之前轉換提示輸入。例如,您可能會想要從任何提供的字串中移除空格。為了完成此操作,許多提示函數都提供了 transform 參數,它會接受閉包

$name = text(
label: 'What is your name?',
transform: fn (string $value) => trim($value),
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);

表單

通常,您會需要依序顯示多個提示,以在執行其他操作之前收集資訊。您可以使用 form 函式建立一組群組化的提示,供使用者填寫。

use function Laravel\Prompts\form;
 
$responses = form()
->text('What is your name?', required: true)
->password('What is your password?', validate: ['password' => 'min:8'])
->confirm('Do you accept the terms?')
->submit();

submit 方法會傳回一個數值索引的陣列,其中包含表單中所有提示的回應。但是,您可以透過 name 參數為每個提示提供名稱。當提供名稱時,可以使用該名稱來存取已命名的提示的回應。

use App\Models\User;
use function Laravel\Prompts\form;
 
$responses = form()
->text('What is your name?', required: true, name: 'name')
->password(
label: 'What is your password?',
validate: ['password' => 'min:8'],
name: 'password'
)
->confirm('Do you accept the terms?')
->submit();
 
User::create([
'name' => $responses['name'],
'password' => $responses['password'],
]);

使用 form 函式的主要好處是,使用者可以使用 CTRL + U 返回表單中先前的提示。這允許使用者修正錯誤或變更選擇,而無需取消並重新啟動整個表單。

如果您需要更精細地控制表單中的提示,您可以調用 add 方法,而不是直接呼叫其中一個提示函式。add 方法會傳遞使用者先前提供的所有回應。

use function Laravel\Prompts\form;
use function Laravel\Prompts\outro;
 
$responses = form()
->text('What is your name?', required: true, name: 'name')
->add(function ($responses) {
return text("How old are you, {$responses['name']}?");
}, name: 'age')
->submit();
 
outro("Your name is {$responses['name']} and you are {$responses['age']} years old.");

資訊訊息

noteinfowarningerroralert 函式可用於顯示資訊訊息。

use function Laravel\Prompts\info;
 
info('Package installed successfully.');

表格

table 函式可以輕鬆顯示多個資料列和資料欄。您只需要提供資料欄名稱和表格的資料即可。

use function Laravel\Prompts\table;
 
table(
headers: ['Name', 'Email'],
rows: User::all(['name', 'email'])->toArray()
);

旋轉

spin 函式會顯示一個旋轉指示器,並在執行指定的 Callback 時顯示可選訊息。它用於指示正在進行的處理程序,並在完成後傳回 Callback 的結果。

use function Laravel\Prompts\spin;
 
$response = spin(
message: 'Fetching response...',
callback: fn () => Http::get('http://example.com')
);
exclamation

spin 函式需要 pcntl PHP 擴充功能來產生旋轉指示器的動畫效果。當此擴充功能不可用時,將會顯示旋轉指示器的靜態版本。

進度條

對於長時間執行的任務,顯示進度條來告知使用者任務的完成進度會很有幫助。透過使用 progress 函式,Laravel 會顯示進度條,並在每次迭代給定的可迭代值時推進其進度。

use function Laravel\Prompts\progress;
 
$users = progress(
label: 'Updating users',
steps: User::all(),
callback: fn ($user) => $this->performTask($user)
);

progress 函式的行為類似於 map 函式,並且會傳回一個陣列,其中包含每次迭代您的 Callback 的回傳值。

Callback 也可以接受 Laravel\Prompts\Progress 實例,允許您在每次迭代時修改標籤和提示。

$users = progress(
label: 'Updating users',
steps: User::all(),
callback: function ($user, $progress) {
$progress
->label("Updating {$user->name}")
->hint("Created on {$user->created_at}");
 
return $this->performTask($user);
},
hint: 'This may take some time.'
);

有時,您可能需要更手動地控制進度條的推進方式。首先,定義程序將迭代的總步數。然後,在處理每個項目後,透過 advance 方法推進進度條。

$progress = progress(label: 'Updating users', steps: 10);
 
$users = User::all();
 
$progress->start();
 
foreach ($users as $user) {
$this->performTask($user);
 
$progress->advance();
}
 
$progress->finish();

清除終端

clear 函式可用於清除使用者的終端機。

use function Laravel\Prompts\clear;
 
clear();

終端考量

終端機寬度

如果任何標籤、選項或驗證訊息的長度超過使用者終端機中的「欄」數,則會自動截斷以符合。如果您的使用者可能使用較窄的終端機,請考慮盡量縮短這些字串的長度。為了支援 80 個字元的終端機,通常安全的長度上限為 74 個字元。

終端機高度

對於任何接受 scroll 參數的提示,配置的值將會自動縮減以符合使用者終端機的高度,包括驗證訊息的空間。

不支援的環境和後備方案

Laravel Prompts 支援 macOS、Linux 和 Windows (使用 WSL)。由於 Windows PHP 版本的限制,目前無法在 WSL 之外的 Windows 上使用 Laravel Prompts。

因此,Laravel Prompts 支援退回至替代實作,例如 Symfony Console Question Helper

lightbulb

當將 Laravel Prompts 與 Laravel 框架一起使用時,每個提示的退回機制都已為您配置,並且會在不受支援的環境中自動啟用。

退回條件

如果您未使用 Laravel 或需要自訂何時使用退回行為,您可以將布林值傳遞至 Prompt 類別上的 fallbackWhen 靜態方法。

use Laravel\Prompts\Prompt;
 
Prompt::fallbackWhen(
! $input->isInteractive() || windows_os() || app()->runningUnitTests()
);

退回行為

如果您未使用 Laravel 或需要自訂退回行為,您可以將閉包傳遞至每個提示類別上的 fallbackUsing 靜態方法。

use Laravel\Prompts\TextPrompt;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
 
TextPrompt::fallbackUsing(function (TextPrompt $prompt) use ($input, $output) {
$question = (new Question($prompt->label, $prompt->default ?: null))
->setValidator(function ($answer) use ($prompt) {
if ($prompt->required && $answer === null) {
throw new \RuntimeException(
is_string($prompt->required) ? $prompt->required : 'Required.'
);
}
 
if ($prompt->validate) {
$error = ($prompt->validate)($answer ?? '');
 
if ($error) {
throw new \RuntimeException($error);
}
}
 
return $answer;
});
 
return (new SymfonyStyle($input, $output))
->askQuestion($question);
});

必須為每個提示類別單獨配置退回機制。閉包會接收提示類別的實例,並且必須傳回適合該提示的類型。