#はじめに
Laravel Prompts は、コマンドラインアプリケーションに美しく使いやすいフォームを追加するためのPHPパッケージです。プレースホルダーテキストやバリデーションなど、ブラウザのような機能を備えています。
Laravel Prompts は、Artisanコンソールコマンドでのユーザー入力受付に最適ですが、任意のコマンドラインPHPプロジェクトでも使用できます。
Laravel Prompts は macOS、Linux、WSLを使ったWindowsをサポートしています。詳細は非対応環境とフォールバックのドキュメントをご覧ください。
#インストール
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 を返します。
#パスワード
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 を返します。
#確認
「はい」か「いいえ」の確認をユーザーに求める場合は、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
);
#値の必須化
デフォルトではユーザーは0個以上の選択肢を選べますが、required 引数を渡すと1つ以上の選択を強制できます:
$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 関数の第2引数にクロージャを渡せます。ユーザーが文字を入力するたびに呼ばれ、これまでの入力文字列を受け取り、自動補完用の選択肢配列を返す必要があります:
$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 を返します。
#検索
選択肢が多い場合、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
);
#値の必須化
デフォルトではユーザーは0個以上の選択肢を選べますが、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 / Returnキーを押して続行を確認するまで待機します:
use function Laravel\Prompts\pause;
pause('Press ENTER to continue.');
#情報メッセージ
note、info、warning、error、alert 関数は情報メッセージを表示するために使えます:
use function Laravel\Prompts\info;
info('Package installed successfully.');
#テーブル
table 関数は複数の行と列のデータを簡単に表示できます。カラム名とテーブルのデータを渡すだけです:
use function Laravel\Prompts\table;
table(
['Name', 'Email'],
User::all(['name', 'email'])
);
#スピン
spin 関数は指定したコールバックを実行中にスピナーと任意のメッセージを表示します。処理中であることを示し、完了後にコールバックの結果を返します:
use function Laravel\Prompts\spin;
$response = spin(
fn () => Http::get('http://example.com'),
'Fetching response...'
);
spin 関数はスピナーのアニメーションに pcntl PHP拡張が必要です。この拡張が利用できない場合は静的なスピナーが表示されます。
#プログレスバー
長時間かかる処理では、進捗状況を示すプログレスバーを表示すると便利です。progress 関数を使うと、指定したイテラブルの各イテレーションでプログレスバーが進みます:
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文字程度です。
#ターミナル高さ
scroll 引数を受け付けるプロンプトでは、設定値がユーザーのターミナル高さに合わせて自動的に調整されます。バリデーションメッセージのスペースも含みます。
#非対応環境とフォールバック
Laravel Prompts は macOS、Linux、WSLを使ったWindowsをサポートしています。Windows版PHPの制限により、WSL以外のWindows環境では現在Laravel Promptsを使用できません。
このため、Laravel Prompts は Symfony Console Question Helper のような代替実装へのフォールバックをサポートしています。
LaravelフレームワークでLaravel Promptsを使う場合、各プロンプトのフォールバックは自動的に設定され、非対応環境で有効になります。
#フォールバック条件
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);
});
フォールバックは各プロンプトクラスごとに個別に設定する必要があります。クロージャはプロンプトクラスのインスタンスを受け取り、適切な型の値を返す必要があります。