Laravel has a command-line interface named Artisan. This interface provides the developer a lot of useful commands to speed up the development process.
Furthermore, you may want to extend artisan with your own commands to create and automatizate the unique tasks of your Laravel project. Commands are typically stored in the app/Console/Commands
directory however, you are free to choose your own storage location as long as your commands can be loaded by Composer.
In this article, you'll learn how to create a custom command for artisan easily in Laravel 5.3.
Create and register command
Laravel help you to do everything easier, it has already integrated the make:console NewClassName
command to speed up your development process. This command expects as first argument the name of the class and optionally, the command option to specify directly the name of the command without modify the class.
To create a new console command named quiz:start
with class name QuizStart execute the following command in your console :
php artisan make:command QuizStart --command=quiz:start
Note: in case you don't want to use the console, copy the example class in "Structure of a command"and change the name of the file and class as you wish. Remember too that in previous versions of Laravel < 5.2, instead of make:command
, you'll need to use make:console
.
This should create a QuizStart class in the /app/console/commands
directory with App\Console\Commands
namespace.
Finally, our command is not registered, therefore we need to add it into our /app/console/Kernel.php
file in the $commands
array (provide the class path and name):
protected $commands = [
// Commands\Inspire::class,
'App\Console\Commands\QuizStart'
];
Use php artisan cache:clear
to clear the cache and try executing your command with the previous given name:
php artisan quiz:start
As expected, this command should do nothing, now you only need to learn how to deal with the command.
Structure of a command
To customize the name of your command and description, change the name directly in the class and all the logic of the command will be stored in the handle function.
<?php
#/App/Console/Commands/QuizStart.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class QuizStart extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'quiz:start';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
}
}
Print text
To send output to the console, you can choose between the following method : line, info, comment, question and error methods. Each of these methods will use appropriate ANSI colors for their purpose.
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->line("Some text");
$this->info("Hey, watch this !");
$this->comment("Just a comment passing by");
$this->question("Why did you do that?");
$this->error("Ops, that should not happen.");
}
Command input : arguments and options
Expect arguments and options in the command
If you don't set which parameters or options expects your function, your command will be unable to work, even if you execute it with parameters.
In Laravel, in the signature property (command name) is where we define our arguments and options, directly in the string (unlike older versions of Laravel) :
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'quiz:start {user} {age} {--difficulty=} {--istest=}';
The arguments are registered in our commannd with the simple syntax of {argumentName}
and the options as {--optionName=}
. so now we don't need to create the get options and get arguments methods in our class.
It's syntax is very simple to understand, basically these are all the ways to use arguments and options in our command (if you want more details, please read the docs):
- Argument:
quiz:start
{argument}
. - Optional Argument (note the question mark next to the argument name):
quiz:start
{argument?}
. - Argument with default value:
quiz:start {argument=defaultValue}
. - Boolean Option:
quiz:start --myOption
. - Option with Value:
quiz:start --myOption=
. - Option with Value and Default:
quiz:start --myOption=12
.
Retrieve arguments and options values
If your command needs some values to work (parameters), you'll need to access these values to use them in your command. To achieve this task, you can use the argument and option methods :
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Get single Parameters
$username = $this->argument('user');
$difficulty = $this->option('difficulty');
// Get all
$arguments = $this->arguments();
$options = $this->options();
// Stop execution and ask a question
$answer = $this->ask('What is your name?');
// Ask for sensitive information
$password = $this->secret('What is the password?');
// Choices
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $default);
// Confirmation
if ($this->confirm('Is '.$name.' correct, do you wish to continue? [y|N]')) {
//
}
}
Example
The following function will create an interactive quiz in the console and you need to answer all of them. Once the quiz has been filled out, it will show the answers that you typed.
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$difficulty = $this->option('difficulty');
if(!$difficulty){
$difficulty = 'easy';
}
$this->line('Welcome '.$this->argument('user').", starting test in difficulty : ". $difficulty);
$questions = [
'easy' => [
'How old are you ?', "What is the name of your mother?",
'Do you have 3 parents ?','Do you like Javascript?',
'Do you know what is a JS promise?'
],
'hard' => [
'Why the sky is blue?', "Can a kangaroo jump higher than a house?",
'Do you think i am a bad father?','why the dinosaurs disappeared?',
"why don't whales have gills?"
]
];
$questionsToAsk = $questions[$difficulty];
$answers = [];
foreach($questionsToAsk as $question){
$answer = $this->ask($question);
array_push($answers,$answer);
}
$this->info("Thanks for do the quiz in the console, your answers : ");
for($i = 0;$i <= (count($questionsToAsk) -1 );$i++){
$this->line(($i + 1).') '. $answers[$i]);
}
}
Executing a command from a controller or route
Obviously, as we used the ask method, it shouldn't work however for other methods you would be able to execute the command using :
$exitCode = Artisan::call('quiz:start', [
'user' => 'Carlos', '--difficulty' => 'hard'
]);
If you need more information about artisan, you can read the documentation here. Have fun !