Published on

Crafting Commands with Laravel Prompts

Laravel Prompts was introduced in Laravel 10 as a replacement of the traditional Symphony Console command i/o. It allows you to create interactive commands with more control over the validation of the user input.

A great use case for Laravel Prompts are for upgrading your old console commands you may have for fixing data or whatever 1 off task you typically build with these commands. You can now make them interactive, more user friendly and fun to build!

Several of the existing i/o methods have been recreated in Laravel Prompts. A few of the ones I like to highlight are:

You can see the full list of methods in the Laravel Prompts documentation.

  • Text
  • Select
  • Confirm

To show off the improved user experience, let's take a look at a simple example of a command that will create a new user and assign them a role using the traditional Symphony Console command i/o and then again using Laravel Prompts.

// Traditional Symphony Console command i/o
public function handle()
{
  $name = $this->ask('What is the name of the user?');
  $email = $this->ask('What is the email of the user?');
  $role = $this->choice('What role should the user have?', ['Admin', 'User']);

  if ($this->confirm('Do you wish to continue?')) {
    $user = User::create([
      'name' => $name,
      'email' => $email,
    ]);  

    $user->assignRole($role);

    $this->info('User created successfully.');
  }
}
// Laravel Prompts
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\select;
use function Laravel\Prompts\text;

public function handle()
{
  $name = text(
    label: 'What is the user name?',
    required: true,
    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
    }
  );

  $email = text(
    label: 'What is the user email?',
    required: true,
    validate: fn (string $value) => match (true) {
      ! filter_var($value, FILTER_VALIDATE_EMAIL) => 'The email must be a valid email address.',
      default => null
    }
  );

  $role = select(
    label: 'What role should the user have?',
    options: ['Admin', 'User'],
    default: 'Admin',
    hint: 'The role may be changed at any time.'
  );

  if (confirm('Do you wish to continue?')) {
    $user = User::create([
      'name' => $name,
      'email' => $email,
    ]);

    $user->assignRole($role);

    $this->info('User created successfully.');
  }
}

With Laravel Prompt we can bake the validation right into the prompt. This allows us to have more control over the validation and the user experience. We can also add hints to the prompts to help the user understand what is expected of them.

Another thing I like doing my commands is making all the user input options optional. This allows me to run the command without any user input and have it use the default values. This is great for running the command in a CI/CD pipeline or for running the command in a production environment or in a environment where you don't have access to the command line output like in Laravel Vapor.

protected $signature = 'create-smart-goal
                        {--name= : The name of the user}
                        {--email= : The email of the user}
                        {--role= : The role of the user}';

public function handle()
{
  $name = $this->option('name') ?: text('What is the user name?');
}

Laravel Prompts is a great addition to the Laravel framework and it makes creating interactive commands a breeze and a lot of fun, I hope you found this article helpful and give Laravel Prompts a try in your next command!