Prompts
- はじめに
- インストール
- 利用可能なプロンプト
- バリデーション前の入力変換
- フォーム
- 情報メッセージ
- テーブル
- スピン
- プログレスバー
- ターミナルのクリア
- ターミナルに関する考慮事項
- サポートされていない環境とフォールバック
はじめに
Laravel Prompts は、プレースホルダーテキストやバリデーションなどのブラウザのような機能を備えた、美しくユーザーフレンドリーなフォームをコマンドラインアプリケーションに追加するためのPHPパッケージです。
 
Laravel Promptsは、Artisanコンソールコマンドでのユーザー入力の受け入れに最適ですが、他のコマンドラインPHPプロジェクトでも使用できます。
Laravel Promptsは、macOS、Linux、およびWSL搭載のWindowsをサポートしています。詳細については、サポートされていない環境とフォールバックに関するドキュメントを参照してください。
インストール
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関数を使用できます。ユーザーは矢印キーを使用するか、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(    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');リストがスクロールを開始する前に、最大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(    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']);リストがスクロールを開始する前に、最大5つのオプションが表示されます。scroll引数を渡してこれをカスタマイズできます。
$categories = multiselect(    label: 'What categories should be assigned?',    options: Category::pluck('name', 'id'),    scroll: 10);値を必須にする
デフォルトでは、ユーザーは0個以上のオプションを選択できます。代わりに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関数の2番目の引数としてクロージャを渡すこともできます。クロージャは、ユーザーが入力文字を入力するたびに呼び出されます。クロージャは、これまでのユーザー入力を含む文字列パラメーターを受け入れ、自動補完のオプションの配列を返す必要があります。
$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.');リストがスクロールを開始する前に、最大5つのオプションが表示されます。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.');リストがスクロールし始める前に、最大5つの選択肢が表示されます。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);値を必須にする
デフォルトでは、ユーザーは0個以上のオプションを選択できます。代わりに1個以上のオプションを強制するには、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キーを押して続行する意思を確認するまで待機するために使用できます。
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.");情報メッセージ
note、info、warning、error、alert関数は、情報メッセージを表示するために使用できます。
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関数は、指定されたコールバックの実行中に、オプションのメッセージとともにスピナーを表示します。進行中のプロセスを示し、完了時にコールバックの結果を返します。
use function Laravel\Prompts\spin; $response = spin(    message: 'Fetching response...',    callback: fn () => Http::get('http://example.com'));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関数のように動作し、コールバックの各反復の戻り値を含む配列を返します。
コールバックは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、および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);});フォールバックは、各プロンプトクラスに対して個別に構成する必要があります。クロージャはプロンプトクラスのインスタンスを受け取り、プロンプトに適切な型を返す必要があります。