laravel/prompts
Laravel Prompts adds beautiful, user-friendly interactive forms to PHP CLIs, with browser-like UX such as placeholders and validation. Ideal for Laravel Artisan commands, but works in any command-line PHP project.
Installation:
composer require laravel/prompts
No additional configuration is required—just use the Prompt facade or import the Laravel\Prompts\Prompt class.
First Use Case:
Replace a basic input() or confirm() call in an Artisan command with a Prompt:
use Laravel\Prompts\Prompt;
$name = Prompt::text('What is your name?');
$age = Prompt::number('How old are you?', min: 18, max: 120);
$confirm = Prompt::confirm('Are you sure?', default: false);
Where to Look First:
Laravel\Prompts\Prompt class (all static methods are available).DataTable, Task, Stream).Sequential Prompts: Chain prompts for multi-step CLI forms:
$email = Prompt::email('Enter your email');
$password = Prompt::password('Enter your password', hideInput: true);
$role = Prompt::select('Select a role', ['admin', 'user', 'guest']);
Conditional Logic:
Use Prompt::when() to show/hide prompts based on previous answers:
$isAdmin = Prompt::confirm('Are you an admin?');
$adminDetails = Prompt::when($isAdmin, fn () =>
Prompt::text('Admin notes (optional)')
);
Forms: Group prompts into a structured form with validation:
$form = Prompt::form([
'name' => Prompt::text('Name')->required(),
'age' => Prompt::number('Age')->min(18),
]);
Dynamic Data:
Fetch options asynchronously (e.g., from an API) for select/multiselect:
$users = Http::get('api/users')->json();
$selected = Prompt::multiselect('Select users', $users, perPage: 10);
Progress Tracking:
Use Task for long-running operations:
Prompt::task('Processing files', fn () => sleep(5));
Artisan Commands:
Replace input()/confirm() with Prompt for consistent UX:
protected function handle(): void
{
$this->info('Welcome!');
$name = Prompt::text('Your name');
$this->info("Hello, {$name}!");
}
Testing:
Use Prompt::fake() to mock interactions in tests:
Prompt::fake(['name' => 'John', 'age' => 30]);
$data = Prompt::form([...]);
Custom Components:
Extend existing prompts (e.g., override render() for a select prompt).
Non-Interactive Mode:
Prompts fail silently in non-interactive environments (e.g., CI). Use Prompt::nonInteractive() or check Prompt::isInteractive():
if (!Prompt::isInteractive()) {
throw new RuntimeException('This command requires interactive mode.');
}
Default Values:
Falsy defaults (e.g., 0, false) may not work as expected. Use default: null and handle validation separately.
Windows Compatibility:
Some features (e.g., Spinner, Task) fall back to static rendering if the posix extension is missing. Test on Windows early.
Validation Overrides:
Custom validation closures must return false for invalid input (not null or a string message).
Multibyte Characters:
Textareas or long labels may render incorrectly. Use truncated: true or adjust terminal width.
Ctrl+C to exit. If the terminal hangs, ensure no infinite loops in validation callbacks.hideInput: true (e.g., passwords) may not work on all terminals. Test locally.->rules() for Laravel-style validation:
Prompt::text('Email')->rules('email')->required();
Custom Prompts:
Extend Laravel\Prompts\Prompt or create a new class:
class CustomPrompt extends Prompt
{
public static function custom(): string
{
return self::text('Custom input')->rules('custom:rule');
}
}
Styling:
Override styles via Prompt::style() or use Symfony’s named styles:
Prompt::style('error', 'fg=red;bold');
Non-English Localization:
Prompts use Symfony’s translation system. Override messages in resources/lang/{locale}/prompts.php.
Performance:
For large select/multiselect lists, use perPage or searchable: true to avoid rendering all options at once.
PromptService class for project-wide reuse.subLabel for contextual hints:
Prompt::text('Username', subLabel: 'Must be 8+ chars')->minLength(8);
Prompt::task('Uploading', 100, fn ($progress) => sleep(0.1));
How can I help you explore Laravel packages today?