メインコンテンツまでスキップ

プロンプト

はじめに

Laravel Prompts は、ブラウザのような機能を備えた美しいユーザーフレンドリーなフォームをコマンドラインアプリケーションに追加するためのPHPパッケージです。プレースホルダーテキストやバリデーションなどの機能が含まれています。

Laravel Prompts は、Artisanコンソールコマンド でユーザー入力を受け入れるのに最適ですが、任意のコマンドラインPHPプロジェクトでも使用できます。

注記

Laravel Prompts は macOS、Linux、および Windows with WSL をサポートしています。詳細については、非サポート環境とフォールバック のドキュメントをご覧ください。

インストール

Laravel Prompts は、最新リリースの Laravel にすでに含まれています。

他のPHPプロジェクトにも Composer パッケージマネージャーを使用してインストールできます:

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のvalidatorの機能を活用することもできます。そのためには、validate引数に属性の名前と必要な検証ルールを含む配列を提供してください:

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

テキストエリア

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のvalidatorの機能を活用することもできます。そのためには、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のvalidatorの機能を活用することもできます。そのためには、validate引数に属性名と希望する検証ルールを含む配列を提供してください:

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

確認

ユーザーに「はい」または「いいえ」の確認を求める必要がある場合は、confirm関数を使用できます。ユーザーは矢印キーを使用するか、yまたはnを押して回答を選択できます。この関数はtrueまたはfalseを返します。

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(
'What role should the user have?',
['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'
);

リストがスクロールを開始する前に最大5つのオプションが表示されます。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(
'What permissions should be assigned?',
['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']
);

リストがスクロールを開始する前に最大5つのオプションが表示されます。scroll引数を渡すことでこれをカスタマイズすることができます:

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

ユーザーが簡単にすべてのオプションを選択できるようにするには、canSelectAll引数を使用できます:

$categories = multiselect(

    label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
canSelectAll: true
);

値の必須

デフォルトでは、ユーザーはゼロ個以上のオプションを選択できます。代わりに1つ以上のオプションを強制するには、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(
'What is your name?',
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 の validator の機能を活用することもできます。これを行うには、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(
'Search for the user that should receive the mail',
fn (string $value) => strlen($value) > 0
? User::where('name', 'like', "%{$value}%")->pluck('name', 'id')->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::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);

リストがスクロールを開始する前に最大5つのオプションが表示されます。scroll 引数を渡すことでこれをカスタマイズできます:

$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::where('name', 'like', "%{$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::where('name', 'like', "%{$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::where('name', 'like', "%{$value}%")->pluck('name', 'id')->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::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);

リストがスクロールを開始する前に最大5つのオプションが表示されます。scroll 引数を提供することでこれをカスタマイズできます:

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

値の必須化

デフォルトでは、ユーザーはゼロ個以上のオプションを選択できます。代わりに required 引数を渡すことで、1つ以上のオプションを強制することができます:

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

検証メッセージをカスタマイズしたい場合は、required 引数に文字列を指定することもできます:

$ids = multisearch(
'Search for the users that should receive the mail',
fn (string $value) => strlen($value) > 0
? User::where('name', 'like', "%{$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::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
: [],
validate: function (array $values) {
$optedOut = User::where('name', 'like', '%a%')->findMany($values);

if ($optedOut->isNotEmpty()) {
return $optedOut->pluck('name')->join(', ', ', and ').' have opted out.';
}
}
);

options クロージャが連想配列を返す場合、クロージャは選択されたキーを受け取ります。それ以外の場合は、選択された値を受け取ります。クロージャはエラーメッセージを返すか、検証が成功した場合は null を返すことができます。

一時停止

pause 関数は、ユーザーに情報テキストを表示し、Enter キーを押して進行を確認するのを待つために使用できます:

use function Laravel\Prompts\pause;

pause('Press ENTER to continue.');

フォーム

しばしば、追加のアクションを実行する前に情報を収集するために連続して表示される複数のプロンプトがあるでしょう。ユーザーが完了するためのグループ化されたプロンプトセットを作成するには、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(
'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 メソッドを呼び出すことができます。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.");

情報メッセージ

noteinfowarningerror、およびalert関数を使用して情報メッセージを表示できます:

use function Laravel\Prompts\info;

info('Package installed successfully.');

テーブル

table関数を使用すると、複数の行と列のデータを簡単に表示できます。列名とテーブルのデータを提供するだけで、表示できます:

use function Laravel\Prompts\table;

table(
['Name', 'Email'],
User::all(['name', 'email'])->toArray()
);

スピン

spin関数は、指定されたコールバックを実行する間にオプションのメッセージと一緒にスピナーを表示します。進行中のプロセスを示し、完了時にコールバックの結果を返します:

use function Laravel\Prompts\spin;

$response = spin(
fn () => Http::get('http://example.com'),
'Fetching response...'
);
警告

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関数は、マップ関数のように機能し、コールバックの各反復の戻り値を含む配列を返します。

コールバックは、各反復ごとにラベルとヒントを変更できる\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();

ターミナルの考慮事項

ターミナルの幅

ユーザーのターミナルの「列」の数を超えるラベル、オプション、または検証メッセージの長さがある場合、自動的に切り捨てられます。ユーザーがより狭いターミナルを使用している可能性がある場合は、これらの文字列の長さを最小限に抑えることを検討してください。80文字のターミナルをサポートするために、通常安全な最大長は74文字です。


#### ターミナルの高さ {/terminal-height}

`scroll` 引数を受け入れるプロンプトでは、設定された値は自動的にユーザーのターミナルの高さに合わせて縮小されます。検証メッセージのスペースも含まれます。

#### サポートされていない環境とフォールバック {/fallbacks}

Laravel Prompts は macOS、Linux、および WSL をサポートしています。Windows 版の PHP に制限があるため、現在は WSL の外で Laravel Prompts を Windows で使用することはできません。

この理由から、Laravel Prompts は、[Symfony Console Question Helper](https://symfony.com/doc/7.0/components/console/helpers/questionhelper.html) などの代替実装にフォールバックすることをサポートしています。

:::note
Laravel フレームワークと一緒に Laravel Prompts を使用する場合、各プロンプトのフォールバックはあなたのために設定され、サポートされていない環境で自動的に有効になります。
:::

#### フォールバックの条件 {/fallback-conditions}

Laravel を使用していない場合や、フォールバックの動作が使用されるタイミングをカスタマイズする必要がある場合は、`Prompt` クラスの `fallbackWhen` 静的メソッドにブール値を渡すことができます:

```php
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);
});

フォールバックは各プロンプトクラスごとに個別に設定する必要があります。クロージャはプロンプトクラスのインスタンスを受け取り、プロンプトに適切な型を返す必要があります。