laravel/prompts
Laravel Prompts adds beautiful, user-friendly interactive forms to PHP CLI apps. Ideal for Laravel Artisan commands, with browser-like touches such as placeholders and built-in validation. Usable in any command-line PHP project.
Installation:
composer require laravel/prompts
No additional configuration is required—it works out-of-the-box with Laravel Artisan commands or standalone CLI scripts.
First Use Case:
Replace a basic input() call with a Prompt for richer UX:
use Laravel\Prompts\Prompt;
$name = Prompt::text('What is your name?');
echo "Hello, $name!";
Where to Look First:
Single Prompts: Use for one-off inputs with validation:
$email = Prompt::email('Enter your email', required: true, validator: fn($email) => $email !== 'invalid@example.com');
Forms (Multi-Step): Group related prompts into a structured flow:
$form = Prompt::form([
'name' => Prompt::text('Name'),
'age' => Prompt::number('Age', min: 18),
'subscribe' => Prompt::confirm('Subscribe to newsletter?', default: false),
]);
Conditional Logic: Dynamically show/hide steps based on previous answers:
$form = Prompt::form([
'admin' => Prompt::confirm('Are you an admin?'),
'admin_details' => Prompt::text('Admin details')->when(fn($admin) => $admin),
]);
Advanced Prompts:
$users = Prompt::table('Select a user', collect([['id' => 1, 'name' => 'John']]));
Prompt::progressBar('Processing...', 100)->progress(fn($bar) => $bar->advance());
Prompt::spinner('Thinking...')->spin(fn($spinner) => $spinner->stop());
Prompt::task('Processing', fn($task) => $task->progress(100)->finish());
Integration with Artisan: Replace CLI arguments with prompts in commands:
protected function handle(): void
{
$path = Prompt::path('Select a file', default: 'storage/app/file.txt');
// Use $path...
}
Prompt::text('Username', validator: fn($value) => Str::of($value)->lengthBetween(3, 20));
Prompt::text('Path', default: 'app/Http/Controllers');
try-catch for graceful failures:
try {
$result = Prompt::confirm('Continue?');
} catch (PromptException $e) {
$this->error($e->getMessage());
}
Non-Interactive Environments:
Prompt::nonInteractive() or check Prompt::isInteractive():
if (!Prompt::isInteractive()) {
return; // Skip prompts in CI
}
POSIX Dependency Fixes:
Validation Edge Cases:
Prompt::text('Age', default: '25', validator: fn($age) => (int)$age >= 18);
Multiline Inputs:
Prompt::textarea()) may behave unexpectedly with special characters (e.g., emojis). Test thoroughly.Logger Issues on Windows:
Prompt::hidden() to mask sensitive data (e.g., passwords):
$password = Prompt::hidden('Password');
Prompt::debug();
Prompt::style():
Prompt::style('info', fn($text) => "<fg=blue>{$text}</>");
Custom Prompt Types:
Extend Prompt to create domain-specific inputs:
class DatabasePrompt extends Prompt
{
public static function database(): string
{
return static::select('Database', ['mysql', 'postgres', 'sqlite']);
}
}
Validation Helpers: Reuse validators across prompts:
$validator = fn($value) => Str::of($value)->contains('@');
Prompt::text('Email', validator: $validator);
Prompt::text('Username', validator: $validator);
Localization: Translate prompts using Laravel’s translation system:
Prompt::text(__('prompts.name'), ...);
Prompt::withTerminalWidth(120);
Prompt::withWindowsEOL() for cross-platform compatibility:
Prompt::withWindowsEOL(true);
$form = Prompt::form([...])->withSummary();
select/multiselect from APIs or databases:
$users = User::all()->pluck('name', 'id');
Prompt::select('User', $users);
Prompt::task('Processing', fn($task) => $task->progress(100)->finish());
Prompt::spinner('Fetching data...')->spin(fn($spinner) => $spinner->stop());
How can I help you explore Laravel packages today?