Laravel Console Wizards

Miša Ković
5 min readMar 25, 2020

--

If you’re anything like me, you find console command arguments really annoying. They’re nothing complicated nor hard, but simply keeping track of them and typing them in every time can get tiring. Having to line them all up, making sure you don’t miss any and the command getting inconveniently long is gruesome at the least.

Now one may argue that is a first world problem, and I wouldn’t argue against that. Having to do the tasks that the command handles manually, if even possible, is even worse. But we, developers, have a knack for solving the tiniest of inconveniences and finding alternative strategies to things that bother us only slightly, which is why I want to show you my solution for lengthy commands.

Laravel Console Wizard is a package that allows you to create interactive wizards to gather complex data from the console by asking the user a predefined series of questions. It lets you specify the steps the user has to complete by using the wizard, validate and modify the data the user has provided, alter the flow of the wizard at runtime, etc.

So how does that look for the user? Let’s imagine we rewrote Laravel’s make:controller command to be a wizard. This is how users would use it:

misa:laravel-console-wizard misa$ php artisan make:controllerEnter the name of your controller:
> ArticlesController
Do you want this to be a resource controller? (yes/no) [no]:
> yes
Enter the model for the resource:
> Article
Do you want to make this to be an API controller? (yes/no) [no]:
> no
misa:laravel-console-wizard misa$

And that’s it. Inside the source code of the command, you, the developer, would have access to this kind of data:

array:4 [
"name" => "ArticlesController"
"is_resource" => true
"model" => "Article"
"is_api" => false
]

Pretty neat, ha? You must be wondering: “How many if statements did this guy have to write to get this kind of flow?”. Well, the truth is, just one. Here is what the code of the wizard looks like:

<?php

namespace App\Console\Commands;

use Shomisha\LaravelConsoleWizard\Command\Wizard;
use Shomisha\LaravelConsoleWizard\Contracts\Step;
use Shomisha\LaravelConsoleWizard\Steps\ConfirmStep;
use Shomisha\LaravelConsoleWizard\Steps\TextStep;

class MakeControllerCommand extends Wizard
{
protected $signature = 'make:controller';

protected $description = 'Create a controller';

function getSteps(): array
{
return [
'name' => new TextStep(
'Enter the name of your controller'
),
'is_resource' => new ConfirmStep(
'Do you want this to be a resource controller?'
),
'is_invokable' => new ConfirmStep(
'Do you want to make this controller invokable?'
),
];
}

public function answeredIsResource(Step $step, bool $isResource)
{
if ($isResource) {
$this->skip('is_invokable');
$this->followUp('is_api', new ConfirmStep(
'Do you want to make this to be an API controller?'
));
$this->followUp('model', new TextStep(
'Enter the model for the resource'
));
}

return $isResource;
}

function completed()
{
/**
* This is where we would perform controller generation.
* In here we have access to all of the users answers via
* the $answers property.
*
* $this->answers->all();
* array:4 [
* "name" => "ArticlesController"
* "is_resource" => true
* "model" => "Article"
* "is_api" => false
* ]
**/
}
}

Notice the if($isResource) statement in the answeredIsResource() method? That’s the one that got away. But still, pretty clean code for a complex wizard flow, isn’t it? I won’t get into the details of how all of this works here, if you’re interested go take a look at the wiki pages for the package.

The way I see it, there are two main advantages to using this approach as opposed to command parameters. The first one is readability, as I previously illustrated, and the second one is the fact that the user will be prompted with all of the options they have, therefore they won’t forget that one parameter, or not use some obscure parameter they haven’t read about.

So, what else can wizards do?

Another great use case for this package is creating commands for manual model creation. Say you wanted to set up multiple environments on multiple servers with different user accounts. Sure, you could use seeders for creating those user accounts, but you would have to manually change them on every server.

With Laravel Console Wizard you can create a wizard which gathers data from you via a few steps and then creates an account. This doesn’t create much value for your end users, but can make your life as a developer easier.

Here’s what you can do:

<?php

namespace App\Console\Commands;

use App\Models\Administrator;
use Shomisha\LaravelConsoleWizard\Command\Wizard;
use Shomisha\LaravelConsoleWizard\Steps\TextStep;
use Shomisha\LaravelConsoleWizard\Steps\UniqueMultipleChoiceStep;

class CreateAdminCommand extends Wizard
{
protected $signature = 'create:admin';

protected $description = 'Create an administrator account.';

function getSteps(): array
{
return [
'name' => new TextStep(
'Enter the name for your administrator account'
),
'email' => new TextStep(
'Enter the email for your administrator account'
),
'password' => new TextStep(
'Enter the password for your administrator account'
),
'permissions' => new UniqueMultipleChoiceStep(
'Choose the permissions for your administrator',
[
'Administrators',
'Users',
'Teachers',
'Classrooms',
'Schedule',
]
),
];
}

function completed()
{
Administrator::create([
'name' => $this->answers->get('name'),
'email' => $this->answers->get('email'),
'password' => bcrypt($this->answers->get('password')),
'permissions' => $this->answers->get('permissions'),
]);
$this->info("Administrator account created.");
}
}

And here’s how easily you can create accounts after that:

misa:laravel-console-wizard misa$ php artisan create:adminEnter the name for your administrator account:
> Staging Administrator
Enter the email for your administrator account:
> admin@staging.com
Enter the password for your administrator account:
> secret
Choose the permissions for your administrator account:
[0] Administrators
[1] Users
[2] Teachers
[3] Classrooms
[4] Schedule
[5] Done
> 0
Choose the permissions for your administrator account:
[1] Users
[2] Teachers
[3] Classrooms
[4] Schedule
[5] Done
> 1
Choose the permissions for your administrator account:
[2] Teachers
[3] Classrooms
[4] Schedule
[5] Done
> 5
Administrator account created.
misa:laravel-console-wizard misa$

And that’s how easily you can create an administrator account. Now you can simply run a single command every time you need to create an account, run through a few steps and you’re good to go.

Thanks for sticking with me through the whole text, I hope you guys like Laravel Console Wizard. Hit me up in the comments if you’ve got any questions, ideas, recommendations.

--

--