Files
laravelDocScrappy/output/12.x/prompts.md
2025-09-02 15:19:23 +02:00

2216 lines
53 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Prompts
* Introduction
* Installation
* Available Prompts
* Text
* Textarea
* Password
* Confirm
* Select
* Multi-select
* Suggest
* Search
* Multi-search
* Pause
* Transforming Input Before Validation
* Forms
* Informational Messages
* Tables
* Spin
* Progress Bar
* Clearing the Terminal
* Terminal Considerations
* Unsupported Environments and Fallbacks
* Testing
## Introduction
[Laravel Prompts](https://github.com/laravel/prompts) is a PHP package for
adding beautiful and user-friendly forms to your command-line applications,
with browser-like features including placeholder text and validation.
![](https://laravel.com/img/docs/prompts-example.png)
Laravel Prompts is perfect for accepting user input in your [Artisan console
commands](/docs/12.x/artisan#writing-commands), but it may also be used in any
command-line PHP project.
Laravel Prompts supports macOS, Linux, and Windows with WSL. For more
information, please see our documentation on unsupported environments &
fallbacks.
## Installation
Laravel Prompts is already included with the latest release of Laravel.
Laravel Prompts may also be installed in your other PHP projects by using the
Composer package manager:
1composer require laravel/prompts
composer require laravel/prompts
## Available Prompts
### Text
The `text` function will prompt the user with the given question, accept their
input, and then return it:
1use function Laravel\Prompts\text;
2 
3$name = text('What is your name?');
use function Laravel\Prompts\text;
$name = text('What is your name?');
You may also include placeholder text, a default value, and an informational
hint:
1$name = text(
2 label: 'What is your name?',
3 placeholder: 'E.g. Taylor Otwell',
4 default: $user?->name,
5 hint: 'This will be displayed on your profile.'
6);
$name = text(
label: 'What is your name?',
placeholder: 'E.g. Taylor Otwell',
default: $user?->name,
hint: 'This will be displayed on your profile.'
);
#### Required Values
If you require a value to be entered, you may pass the `required` argument:
1$name = text(
2 label: 'What is your name?',
3 required: true
4);
$name = text(
label: 'What is your name?',
required: true
);
If you would like to customize the validation message, you may also pass a
string:
1$name = text(
2 label: 'What is your name?',
3 required: 'Your name is required.'
4);
$name = text(
label: 'What is your name?',
required: 'Your name is required.'
);
#### Additional Validation
Finally, if you would like to perform additional validation logic, you may
pass a closure to the `validate` argument:
1$name = text(
2 label: 'What is your name?',
3 validate: fn (string $value) => match (true) {
4 strlen($value) < 3 => 'The name must be at least 3 characters.',
5 strlen($value) > 255 => 'The name must not exceed 255 characters.',
6 default => null
7 }
8);
$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
}
);
The closure will receive the value that has been entered and may return an
error message, or `null` if the validation passes.
Alternatively, you may leverage the power of Laravel's
[validator](/docs/12.x/validation). To do so, provide an array containing the
name of the attribute and the desired validation rules to the `validate`
argument:
1$name = text(
2 label: 'What is your name?',
3 validate: ['name' => 'required|max:255|unique:users']
4);
$name = text(
label: 'What is your name?',
validate: ['name' => 'required|max:255|unique:users']
);
### Textarea
The `textarea` function will prompt the user with the given question, accept
their input via a multi-line textarea, and then return it:
1use function Laravel\Prompts\textarea;
2 
3$story = textarea('Tell me a story.');
use function Laravel\Prompts\textarea;
$story = textarea('Tell me a story.');
You may also include placeholder text, a default value, and an informational
hint:
1$story = textarea(
2 label: 'Tell me a story.',
3 placeholder: 'This is a story about...',
4 hint: 'This will be displayed on your profile.'
5);
$story = textarea(
label: 'Tell me a story.',
placeholder: 'This is a story about...',
hint: 'This will be displayed on your profile.'
);
#### Required Values
If you require a value to be entered, you may pass the `required` argument:
1$story = textarea(
2 label: 'Tell me a story.',
3 required: true
4);
$story = textarea(
label: 'Tell me a story.',
required: true
);
If you would like to customize the validation message, you may also pass a
string:
1$story = textarea(
2 label: 'Tell me a story.',
3 required: 'A story is required.'
4);
$story = textarea(
label: 'Tell me a story.',
required: 'A story is required.'
);
#### Additional Validation
Finally, if you would like to perform additional validation logic, you may
pass a closure to the `validate` argument:
1$story = textarea(
2 label: 'Tell me a story.',
3 validate: fn (string $value) => match (true) {
4 strlen($value) < 250 => 'The story must be at least 250 characters.',
5 strlen($value) > 10000 => 'The story must not exceed 10,000 characters.',
6 default => null
7 }
8);
$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
}
);
The closure will receive the value that has been entered and may return an
error message, or `null` if the validation passes.
Alternatively, you may leverage the power of Laravel's
[validator](/docs/12.x/validation). To do so, provide an array containing the
name of the attribute and the desired validation rules to the `validate`
argument:
1$story = textarea(
2 label: 'Tell me a story.',
3 validate: ['story' => 'required|max:10000']
4);
$story = textarea(
label: 'Tell me a story.',
validate: ['story' => 'required|max:10000']
);
### Password
The `password` function is similar to the `text` function, but the user's
input will be masked as they type in the console. This is useful when asking
for sensitive information such as passwords:
1use function Laravel\Prompts\password;
2 
3$password = password('What is your password?');
use function Laravel\Prompts\password;
$password = password('What is your password?');
You may also include placeholder text and an informational hint:
1$password = password(
2 label: 'What is your password?',
3 placeholder: 'password',
4 hint: 'Minimum 8 characters.'
5);
$password = password(
label: 'What is your password?',
placeholder: 'password',
hint: 'Minimum 8 characters.'
);
#### Required Values
If you require a value to be entered, you may pass the `required` argument:
1$password = password(
2 label: 'What is your password?',
3 required: true
4);
$password = password(
label: 'What is your password?',
required: true
);
If you would like to customize the validation message, you may also pass a
string:
1$password = password(
2 label: 'What is your password?',
3 required: 'The password is required.'
4);
$password = password(
label: 'What is your password?',
required: 'The password is required.'
);
#### Additional Validation
Finally, if you would like to perform additional validation logic, you may
pass a closure to the `validate` argument:
1$password = password(
2 label: 'What is your password?',
3 validate: fn (string $value) => match (true) {
4 strlen($value) < 8 => 'The password must be at least 8 characters.',
5 default => null
6 }
7);
$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
}
);
The closure will receive the value that has been entered and may return an
error message, or `null` if the validation passes.
Alternatively, you may leverage the power of Laravel's
[validator](/docs/12.x/validation). To do so, provide an array containing the
name of the attribute and the desired validation rules to the `validate`
argument:
1$password = password(
2 label: 'What is your password?',
3 validate: ['password' => 'min:8']
4);
$password = password(
label: 'What is your password?',
validate: ['password' => 'min:8']
);
### Confirm
If you need to ask the user for a "yes or no" confirmation, you may use the
`confirm` function. Users may use the arrow keys or press `y` or `n` to select
their response. This function will return either `true` or `false`.
1use function Laravel\Prompts\confirm;
2 
3$confirmed = confirm('Do you accept the terms?');
use function Laravel\Prompts\confirm;
$confirmed = confirm('Do you accept the terms?');
You may also include a default value, customized wording for the "Yes" and
"No" labels, and an informational hint:
1$confirmed = confirm(
2 label: 'Do you accept the terms?',
3 default: false,
4 yes: 'I accept',
5 no: 'I decline',
6 hint: 'The terms must be accepted to continue.'
7);
$confirmed = confirm(
label: 'Do you accept the terms?',
default: false,
yes: 'I accept',
no: 'I decline',
hint: 'The terms must be accepted to continue.'
);
#### Requiring "Yes"
If necessary, you may require your users to select "Yes" by passing the
`required` argument:
1$confirmed = confirm(
2 label: 'Do you accept the terms?',
3 required: true
4);
$confirmed = confirm(
label: 'Do you accept the terms?',
required: true
);
If you would like to customize the validation message, you may also pass a
string:
1$confirmed = confirm(
2 label: 'Do you accept the terms?',
3 required: 'You must accept the terms to continue.'
4);
$confirmed = confirm(
label: 'Do you accept the terms?',
required: 'You must accept the terms to continue.'
);
### Select
If you need the user to select from a predefined set of choices, you may use
the `select` function:
1use function Laravel\Prompts\select;
2 
3$role = select(
4 label: 'What role should the user have?',
5 options: ['Member', 'Contributor', 'Owner']
6);
use function Laravel\Prompts\select;
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner']
);
You may also specify the default choice and an informational hint:
1$role = select(
2 label: 'What role should the user have?',
3 options: ['Member', 'Contributor', 'Owner'],
4 default: 'Owner',
5 hint: 'The role may be changed at any time.'
6);
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner'],
default: 'Owner',
hint: 'The role may be changed at any time.'
);
You may also pass an associative array to the `options` argument to have the
selected key returned instead of its value:
1$role = select(
2 label: 'What role should the user have?',
3 options: [
4 'member' => 'Member',
5 'contributor' => 'Contributor',
6 'owner' => 'Owner',
7 ],
8 default: 'owner'
9);
$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
default: 'owner'
);
Up to five options will be displayed before the list begins to scroll. You may
customize this by passing the `scroll` argument:
1$role = select(
2 label: 'Which category would you like to assign?',
3 options: Category::pluck('name', 'id'),
4 scroll: 10
5);
$role = select(
label: 'Which category would you like to assign?',
options: Category::pluck('name', 'id'),
scroll: 10
);
#### Additional Validation
Unlike other prompt functions, the `select` function doesn't accept the
`required` argument because it is not possible to select nothing. However, you
may pass a closure to the `validate` argument if you need to present an option
but prevent it from being selected:
1$role = select(
2 label: 'What role should the user have?',
3 options: [
4 'member' => 'Member',
5 'contributor' => 'Contributor',
6 'owner' => 'Owner',
7 ],
8 validate: fn (string $value) =>
9 $value === 'owner' && User::where('role', 'owner')->exists()
10 ? 'An owner already exists.'
11 : null
12);
$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
);
If the `options` argument is an associative array, then the closure will
receive the selected key, otherwise it will receive the selected value. The
closure may return an error message, or `null` if the validation passes.
### Multi-select
If you need the user to be able to select multiple options, you may use the
`multiselect` function:
1use function Laravel\Prompts\multiselect;
2 
3$permissions = multiselect(
4 label: 'What permissions should be assigned?',
5 options: ['Read', 'Create', 'Update', 'Delete']
6);
use function Laravel\Prompts\multiselect;
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: ['Read', 'Create', 'Update', 'Delete']
);
You may also specify default choices and an informational hint:
1use function Laravel\Prompts\multiselect;
2 
3$permissions = multiselect(
4 label: 'What permissions should be assigned?',
5 options: ['Read', 'Create', 'Update', 'Delete'],
6 default: ['Read', 'Create'],
7 hint: 'Permissions may be updated at any time.'
8);
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.'
);
You may also pass an associative array to the `options` argument to return the
selected options' keys instead of their values:
1$permissions = multiselect(
2 label: 'What permissions should be assigned?',
3 options: [
4 'read' => 'Read',
5 'create' => 'Create',
6 'update' => 'Update',
7 'delete' => 'Delete',
8 ],
9 default: ['read', 'create']
10);
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
default: ['read', 'create']
);
Up to five options will be displayed before the list begins to scroll. You may
customize this by passing the `scroll` argument:
1$categories = multiselect(
2 label: 'What categories should be assigned?',
3 options: Category::pluck('name', 'id'),
4 scroll: 10
5);
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
scroll: 10
);
#### Requiring a Value
By default, the user may select zero or more options. You may pass the
`required` argument to enforce one or more options instead:
1$categories = multiselect(
2 label: 'What categories should be assigned?',
3 options: Category::pluck('name', 'id'),
4 required: true
5);
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: true
);
If you would like to customize the validation message, you may provide a
string to the `required` argument:
1$categories = multiselect(
2 label: 'What categories should be assigned?',
3 options: Category::pluck('name', 'id'),
4 required: 'You must select at least one category'
5);
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: 'You must select at least one category'
);
#### Additional Validation
You may pass a closure to the `validate` argument if you need to present an
option but prevent it from being selected:
1$permissions = multiselect(
2 label: 'What permissions should the user have?',
3 options: [
4 'read' => 'Read',
5 'create' => 'Create',
6 'update' => 'Update',
7 'delete' => 'Delete',
8 ],
9 validate: fn (array $values) => ! in_array('read', $values)
10 ? 'All users require the read permission.'
11 : null
12);
$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
);
If the `options` argument is an associative array then the closure will
receive the selected keys, otherwise it will receive the selected values. The
closure may return an error message, or `null` if the validation passes.
### Suggest
The `suggest` function can be used to provide auto-completion for possible
choices. The user can still provide any answer, regardless of the auto-
completion hints:
1use function Laravel\Prompts\suggest;
2 
3$name = suggest('What is your name?', ['Taylor', 'Dayle']);
use function Laravel\Prompts\suggest;
$name = suggest('What is your name?', ['Taylor', 'Dayle']);
Alternatively, you may pass a closure as the second argument to the `suggest`
function. The closure will be called each time the user types an input
character. The closure should accept a string parameter containing the user's
input so far and return an array of options for auto-completion:
1$name = suggest(
2 label: 'What is your name?',
3 options: fn ($value) => collect(['Taylor', 'Dayle'])
4 ->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
5)
$name = suggest(
label: 'What is your name?',
options: fn ($value) => collect(['Taylor', 'Dayle'])
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
)
You may also include placeholder text, a default value, and an informational
hint:
1$name = suggest(
2 label: 'What is your name?',
3 options: ['Taylor', 'Dayle'],
4 placeholder: 'E.g. Taylor',
5 default: $user?->name,
6 hint: 'This will be displayed on your profile.'
7);
$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 Values
If you require a value to be entered, you may pass the `required` argument:
1$name = suggest(
2 label: 'What is your name?',
3 options: ['Taylor', 'Dayle'],
4 required: true
5);
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: true
);
If you would like to customize the validation message, you may also pass a
string:
1$name = suggest(
2 label: 'What is your name?',
3 options: ['Taylor', 'Dayle'],
4 required: 'Your name is required.'
5);
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: 'Your name is required.'
);
#### Additional Validation
Finally, if you would like to perform additional validation logic, you may
pass a closure to the `validate` argument:
1$name = suggest(
2 label: 'What is your name?',
3 options: ['Taylor', 'Dayle'],
4 validate: fn (string $value) => match (true) {
5 strlen($value) < 3 => 'The name must be at least 3 characters.',
6 strlen($value) > 255 => 'The name must not exceed 255 characters.',
7 default => null
8 }
9);
$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
}
);
The closure will receive the value that has been entered and may return an
error message, or `null` if the validation passes.
Alternatively, you may leverage the power of Laravel's
[validator](/docs/12.x/validation). To do so, provide an array containing the
name of the attribute and the desired validation rules to the `validate`
argument:
1$name = suggest(
2 label: 'What is your name?',
3 options: ['Taylor', 'Dayle'],
4 validate: ['name' => 'required|min:3|max:255']
5);
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
validate: ['name' => 'required|min:3|max:255']
);
### Search
If you have a lot of options for the user to select from, the `search`
function allows the user to type a search query to filter the results before
using the arrow keys to select an option:
1use function Laravel\Prompts\search;
2 
3$id = search(
4 label: 'Search for the user that should receive the mail',
5 options: fn (string $value) => strlen($value) > 0
6 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
7 : []
8);
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()
: []
);
The closure will receive the text that has been typed by the user so far and
must return an array of options. If you return an associative array then the
selected option's key will be returned, otherwise its value will be returned
instead.
When filtering an array where you intend to return the value, you should use
the `array_values` function or the `values` Collection method to ensure the
array doesn't become associative:
1$names = collect(['Taylor', 'Abigail']);
2 
3$selected = search(
4 label: 'Search for the user that should receive the mail',
5 options: fn (string $value) => $names
6 ->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
7 ->values()
8 ->all(),
9);
$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(),
);
You may also include placeholder text and an informational hint:
1$id = search(
2 label: 'Search for the user that should receive the mail',
3 placeholder: 'E.g. Taylor Otwell',
4 options: fn (string $value) => strlen($value) > 0
5 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
6 : [],
7 hint: 'The user will receive an email immediately.'
8);
$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.'
);
Up to five options will be displayed before the list begins to scroll. You may
customize this by passing the `scroll` argument:
1$id = search(
2 label: 'Search for the user that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 scroll: 10
7);
$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
);
#### Additional Validation
If you would like to perform additional validation logic, you may pass a
closure to the `validate` argument:
1$id = search(
2 label: 'Search for the user that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 validate: function (int|string $value) {
7 $user = User::findOrFail($value);
8 
9 if ($user->opted_out) {
10 return 'This user has opted-out of receiving mail.';
11 }
12 }
13);
$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.';
}
}
);
If the `options` closure returns an associative array, then the closure will
receive the selected key, otherwise, it will receive the selected value. The
closure may return an error message, or `null` if the validation passes.
### Multi-search
If you have a lot of searchable options and need the user to be able to select
multiple items, the `multisearch` function allows the user to type a search
query to filter the results before using the arrow keys and space-bar to
select options:
1use function Laravel\Prompts\multisearch;
2 
3$ids = multisearch(
4 'Search for the users that should receive the mail',
5 fn (string $value) => strlen($value) > 0
6 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
7 : []
8);
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()
: []
);
The closure will receive the text that has been typed by the user so far and
must return an array of options. If you return an associative array then the
selected options' keys will be returned; otherwise, their values will be
returned instead.
When filtering an array where you intend to return the value, you should use
the `array_values` function or the `values` Collection method to ensure the
array doesn't become associative:
1$names = collect(['Taylor', 'Abigail']);
2 
3$selected = multisearch(
4 label: 'Search for the users that should receive the mail',
5 options: fn (string $value) => $names
6 ->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
7 ->values()
8 ->all(),
9);
$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(),
);
You may also include placeholder text and an informational hint:
1$ids = multisearch(
2 label: 'Search for the users that should receive the mail',
3 placeholder: 'E.g. Taylor Otwell',
4 options: fn (string $value) => strlen($value) > 0
5 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
6 : [],
7 hint: 'The user will receive an email immediately.'
8);
$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.'
);
Up to five options will be displayed before the list begins to scroll. You may
customize this by providing the `scroll` argument:
1$ids = multisearch(
2 label: 'Search for the users that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 scroll: 10
7);
$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
);
#### Requiring a Value
By default, the user may select zero or more options. You may pass the
`required` argument to enforce one or more options instead:
1$ids = multisearch(
2 label: 'Search for the users that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 required: true
7);
$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
);
If you would like to customize the validation message, you may also provide a
string to the `required` argument:
1$ids = multisearch(
2 label: 'Search for the users that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 required: 'You must select at least one user.'
7);
$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.'
);
#### Additional Validation
If you would like to perform additional validation logic, you may pass a
closure to the `validate` argument:
1$ids = multisearch(
2 label: 'Search for the users that should receive the mail',
3 options: fn (string $value) => strlen($value) > 0
4 ? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
5 : [],
6 validate: function (array $values) {
7 $optedOut = User::whereLike('name', '%a%')->findMany($values);
8 
9 if ($optedOut->isNotEmpty()) {
10 return $optedOut->pluck('name')->join(', ', ', and ').' have opted out.';
11 }
12 }
13);
$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.';
}
}
);
If the `options` closure returns an associative array, then the closure will
receive the selected keys; otherwise, it will receive the selected values. The
closure may return an error message, or `null` if the validation passes.
### Pause
The `pause` function may be used to display informational text to the user and
wait for them to confirm their desire to proceed by pressing the Enter /
Return key:
1use function Laravel\Prompts\pause;
2 
3pause('Press ENTER to continue.');
use function Laravel\Prompts\pause;
pause('Press ENTER to continue.');
## Transforming Input Before Validation
Sometimes you may want to transform the prompt input before validation takes
place. For example, you may wish to remove white space from any provided
strings. To accomplish this, many of the prompt functions provide a
`transform` argument, which accepts a closure:
1$name = text(
2 label: 'What is your name?',
3 transform: fn (string $value) => trim($value),
4 validate: fn (string $value) => match (true) {
5 strlen($value) < 3 => 'The name must be at least 3 characters.',
6 strlen($value) > 255 => 'The name must not exceed 255 characters.',
7 default => null
8 }
9);
$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
}
);
## Forms
Often, you will have multiple prompts that will be displayed in sequence to
collect information before performing additional actions. You may use the
`form` function to create a grouped set of prompts for the user to complete:
1use function Laravel\Prompts\form;
2 
3$responses = form()
4 ->text('What is your name?', required: true)
5 ->password('What is your password?', validate: ['password' => 'min:8'])
6 ->confirm('Do you accept the terms?')
7 ->submit();
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();
The `submit` method will return a numerically indexed array containing all of
the responses from the form's prompts. However, you may provide a name for
each prompt via the `name` argument. When a name is provided, the named
prompt's response may be accessed via that name:
1use App\Models\User;
2use function Laravel\Prompts\form;
3 
4$responses = form()
5 ->text('What is your name?', required: true, name: 'name')
6 ->password(
7 label: 'What is your password?',
8 validate: ['password' => 'min:8'],
9 name: 'password'
10 )
11 ->confirm('Do you accept the terms?')
12 ->submit();
13 
14User::create([
15 'name' => $responses['name'],
16 'password' => $responses['password'],
17]);
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'],
]);
The primary benefit of using the `form` function is the ability for the user
to return to previous prompts in the form using `CTRL + U`. This allows the
user to fix mistakes or alter selections without needing to cancel and restart
the entire form.
If you need more granular control over a prompt in a form, you may invoke the
`add` method instead of calling one of the prompt functions directly. The
`add` method is passed all previous responses provided by the user:
1use function Laravel\Prompts\form;
2use function Laravel\Prompts\outro;
3use function Laravel\Prompts\text;
4 
5$responses = form()
6 ->text('What is your name?', required: true, name: 'name')
7 ->add(function ($responses) {
8 return text("How old are you, {$responses['name']}?");
9 }, name: 'age')
10 ->submit();
11 
12outro("Your name is {$responses['name']} and you are {$responses['age']} years old.");
use function Laravel\Prompts\form;
use function Laravel\Prompts\outro;
use function Laravel\Prompts\text;
$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.");
## Informational Messages
The `note`, `info`, `warning`, `error`, and `alert` functions may be used to
display informational messages:
1use function Laravel\Prompts\info;
2 
3info('Package installed successfully.');
use function Laravel\Prompts\info;
info('Package installed successfully.');
## Tables
The `table` function makes it easy to display multiple rows and columns of
data. All you need to do is provide the column names and the data for the
table:
1use function Laravel\Prompts\table;
2 
3table(
4 headers: ['Name', 'Email'],
5 rows: User::all(['name', 'email'])->toArray()
6);
use function Laravel\Prompts\table;
table(
headers: ['Name', 'Email'],
rows: User::all(['name', 'email'])->toArray()
);
## Spin
The `spin` function displays a spinner along with an optional message while
executing a specified callback. It serves to indicate ongoing processes and
returns the callback's results upon completion:
1use function Laravel\Prompts\spin;
2 
3$response = spin(
4 callback: fn () => Http::get('http://example.com'),
5 message: 'Fetching response...'
6);
use function Laravel\Prompts\spin;
$response = spin(
callback: fn () => Http::get('http://example.com'),
message: 'Fetching response...'
);
The `spin` function requires the
[PCNTL](https://www.php.net/manual/en/book.pcntl.php) PHP extension to animate
the spinner. When this extension is not available, a static version of the
spinner will appear instead.
## Progress Bars
For long running tasks, it can be helpful to show a progress bar that informs
users how complete the task is. Using the `progress` function, Laravel will
display a progress bar and advance its progress for each iteration over a
given iterable value:
1use function Laravel\Prompts\progress;
2 
3$users = progress(
4 label: 'Updating users',
5 steps: User::all(),
6 callback: fn ($user) => $this->performTask($user)
7);
use function Laravel\Prompts\progress;
$users = progress(
label: 'Updating users',
steps: User::all(),
callback: fn ($user) => $this->performTask($user)
);
The `progress` function acts like a map function and will return an array
containing the return value of each iteration of your callback.
The callback may also accept the `Laravel\Prompts\Progress` instance, allowing
you to modify the label and hint on each iteration:
1$users = progress(
2 label: 'Updating users',
3 steps: User::all(),
4 callback: function ($user, $progress) {
5 $progress
6 ->label("Updating {$user->name}")
7 ->hint("Created on {$user->created_at}");
8 
9 return $this->performTask($user);
10 },
11 hint: 'This may take some time.'
12);
$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.'
);
Sometimes, you may need more manual control over how a progress bar is
advanced. First, define the total number of steps the process will iterate
through. Then, advance the progress bar via the `advance` method after
processing each item:
1$progress = progress(label: 'Updating users', steps: 10);
2 
3$users = User::all();
4 
5$progress->start();
6 
7foreach ($users as $user) {
8 $this->performTask($user);
9 
10 $progress->advance();
11}
12 
13$progress->finish();
$progress = progress(label: 'Updating users', steps: 10);
$users = User::all();
$progress->start();
foreach ($users as $user) {
$this->performTask($user);
$progress->advance();
}
$progress->finish();
## Clearing the Terminal
The `clear` function may be used to clear the user's terminal:
1use function Laravel\Prompts\clear;
2 
3clear();
use function Laravel\Prompts\clear;
clear();
## Terminal Considerations
#### Terminal Width
If the length of any label, option, or validation message exceeds the number
of "columns" in the user's terminal, it will be automatically truncated to
fit. Consider minimizing the length of these strings if your users may be
using narrower terminals. A typically safe maximum length is 74 characters to
support an 80-character terminal.
#### Terminal Height
For any prompts that accept the `scroll` argument, the configured value will
automatically be reduced to fit the height of the user's terminal, including
space for a validation message.
## Unsupported Environments and Fallbacks
Laravel Prompts supports macOS, Linux, and Windows with WSL. Due to
limitations in the Windows version of PHP, it is not currently possible to use
Laravel Prompts on Windows outside of WSL.
For this reason, Laravel Prompts supports falling back to an alternative
implementation such as the [Symfony Console Question
Helper](https://symfony.com/doc/current/components/console/helpers/questionhelper.html).
When using Laravel Prompts with the Laravel framework, fallbacks for each
prompt have been configured for you and will be automatically enabled in
unsupported environments.
#### Fallback Conditions
If you are not using Laravel or need to customize when the fallback behavior
is used, you may pass a boolean to the `fallbackWhen` static method on the
`Prompt` class:
1use Laravel\Prompts\Prompt;
2 
3Prompt::fallbackWhen(
4 ! $input->isInteractive() || windows_os() || app()->runningUnitTests()
5);
use Laravel\Prompts\Prompt;
Prompt::fallbackWhen(
! $input->isInteractive() || windows_os() || app()->runningUnitTests()
);
#### Fallback Behavior
If you are not using Laravel or need to customize the fallback behavior, you
may pass a closure to the `fallbackUsing` static method on each prompt class:
1use Laravel\Prompts\TextPrompt;
2use Symfony\Component\Console\Question\Question;
3use Symfony\Component\Console\Style\SymfonyStyle;
4 
5TextPrompt::fallbackUsing(function (TextPrompt $prompt) use ($input, $output) {
6 $question = (new Question($prompt->label, $prompt->default ?: null))
7 ->setValidator(function ($answer) use ($prompt) {
8 if ($prompt->required && $answer === null) {
9 throw new \RuntimeException(
10 is_string($prompt->required) ? $prompt->required : 'Required.'
11 );
12 }
13 
14 if ($prompt->validate) {
15 $error = ($prompt->validate)($answer ?? '');
16 
17 if ($error) {
18 throw new \RuntimeException($error);
19 }
20 }
21 
22 return $answer;
23 });
24 
25 return (new SymfonyStyle($input, $output))
26 ->askQuestion($question);
27});
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);
});
Fallbacks must be configured individually for each prompt class. The closure
will receive an instance of the prompt class and must return an appropriate
type for the prompt.
## Testing
Laravel provides a variety of methods for testing that your command displays
the expected Prompt messages:
Pest PHPUnit
1test('report generation', function () {
2 $this->artisan('report:generate')
3 ->expectsPromptsInfo('Welcome to the application!')
4 ->expectsPromptsWarning('This action cannot be undone')
5 ->expectsPromptsError('Something went wrong')
6 ->expectsPromptsAlert('Important notice!')
7 ->expectsPromptsIntro('Starting process...')
8 ->expectsPromptsOutro('Process completed!')
9 ->expectsPromptsTable(
10 headers: ['Name', 'Email'],
11 rows: [
12 ['Taylor Otwell', '[[email protected]](/cdn-cgi/l/email-protection)'],
13 ['Jason Beggs', '[[email protected]](/cdn-cgi/l/email-protection)'],
14 ]
15 )
16 ->assertExitCode(0);
17});
test('report generation', function () {
$this->artisan('report:generate')
->expectsPromptsInfo('Welcome to the application!')
->expectsPromptsWarning('This action cannot be undone')
->expectsPromptsError('Something went wrong')
->expectsPromptsAlert('Important notice!')
->expectsPromptsIntro('Starting process...')
->expectsPromptsOutro('Process completed!')
->expectsPromptsTable(
headers: ['Name', 'Email'],
rows: [
['Taylor Otwell', '[[email protected]](/cdn-cgi/l/email-protection)'],
['Jason Beggs', '[[email protected]](/cdn-cgi/l/email-protection)'],
]
)
->assertExitCode(0);
});
1public function test_report_generation(): void
2{
3 $this->artisan('report:generate')
4 ->expectsPromptsInfo('Welcome to the application!')
5 ->expectsPromptsWarning('This action cannot be undone')
6 ->expectsPromptsError('Something went wrong')
7 ->expectsPromptsAlert('Important notice!')
8 ->expectsPromptsIntro('Starting process...')
9 ->expectsPromptsOutro('Process completed!')
10 ->expectsPromptsTable(
11 headers: ['Name', 'Email'],
12 rows: [
13 ['Taylor Otwell', '[[email protected]](/cdn-cgi/l/email-protection)'],
14 ['Jason Beggs', '[[email protected]](/cdn-cgi/l/email-protection)'],
15 ]
16 )
17 ->assertExitCode(0);
18}
public function test_report_generation(): void
{
$this->artisan('report:generate')
->expectsPromptsInfo('Welcome to the application!')
->expectsPromptsWarning('This action cannot be undone')
->expectsPromptsError('Something went wrong')
->expectsPromptsAlert('Important notice!')
->expectsPromptsIntro('Starting process...')
->expectsPromptsOutro('Process completed!')
->expectsPromptsTable(
headers: ['Name', 'Email'],
rows: [
['Taylor Otwell', '[[email protected]](/cdn-cgi/l/email-protection)'],
['Jason Beggs', '[[email protected]](/cdn-cgi/l/email-protection)'],
]
)
->assertExitCode(0);
}