Laravel Artisan Closure Based Commands

December 7, 2016 —John Koster

Laravel 5.3 introduced a new shorthand syntax to make writing simple Artisan commands much simpler. The console kernel exposes a command($signature, Closure $callback) method. The $signature parameter accepts a command signature string, which will be used to define the input requirements of the command. The $callback parameter accepts a callback function whose body will have access to the underlying Artisan ClosureCommand (the ClosureCommand class is a subclass of the Command superclass) instance. Commands defined using the shorthand syntax can be defined within the commands method as this method is automatically called by the framework when registering Artisan commands.

The following example is written within the context of the App\Console\Kernel.php file:

1<?php
2 
3// ...
4 
5protected function commands()
6{
7 // Register a new command `say:hello` using the shorthand
8 // syntax. This command will be registered automatically
9 // and does not have to be explicitly registered.
10 $this->command('say:hello {name}', function($name) {
11 $this->info("Hello, {$name}");
12 });
13}
14 
15// ...

Similar to registering application routes, the input requirements defined with the commands signature (the value supplied to the $signature parameter) will be automatically passed in as the arguments to the callback function. For example, whatever value was supplied for the {$name} input parameter will be passed along as the argument for the callback function's $name parameter. The following diagram visually explains the flow of data when using the command method:

How data is supplied to arguments

As stated earlier, the function body of the callback has access to a complete
Illuminate\Foundation\Console\ClosureCommand instance; any methods or properties registered on the Command class will be available within the callback body. Also, the command returns the underlying ClosureCommand instance so that it can be modified further:

The ClosureCommand class extends Laravel's Illuminate\Console\Command class. Any methods and features defined on the Command class will also be available to commands registered using the shorthand command syntax. The only significant difference is that the ClosureCommand class defines an extra helper method describe($description).

1// ...
2 
3protected function commands()
4{
5 $this->command('say:hello {name}', function($name) {
6 $favoriteSnack = $this->ask('What is your favorite snack?');
7 
8 $this->info(
9 "Hello, {$name}. Your favorite snack is {$favoriteSnack}!"
10 );
11 });
12}
13 
14// ...

Since the command method returns the underlying ClosureCommand instance, we can make calls to its methods. A typical use case for doing so is to set a description for the command registered using the shorthand syntax:

1// ...
2 
3protected function commands()
4{
5 $this->command('say:hello {name}', function($name) {
6 $favoriteSnack = $this->ask('What is your favorite snack?');
7 
8 $this->info(
9 "Hello, {$name}. Your favorite snack is {$favoriteSnack}!"
10 );
11 })->describe('Give a warm welcome.');
12}
13 
14// ...

Issuing the php artisan say:hello -h command would display help information similar to the following output; notice that the description, command name and arguments have all been set as if they were defined using the class based method of writing Artisan commands (the default options have been omitted from the example output):

1Usage:
2 say:hello <name>
3
4Arguments:
5 name
6
7Help:
8 Give a warm welcome.

#Simplifying Closure Command Registration

For some projects, it might be useful to register Artisan commands using methods similar to how routes are registered with the application. Starting with Laravel 5.3, there is a console.php file available within the applications routes directory. This file is loaded by default from the console kernel's commands method, so any commands defined within the console.php file will made available to your application.

By default, the console.php file contains the following command definition:

1<?php
2 
3use Illuminate\Foundation\Inspiring;
4 
5/*
6|--------------------------------------------------------------------------
7| Console Routes
8|--------------------------------------------------------------------------
9|
10| This file is where you may define all of your Closure based console
11| commands. Each Closure is bound to a command instance allowing a
12| simple approach to interacting with each command's IO methods.
13|
14*/
15Artisan::command('inspire', function () {
16 $this->comment(Inspiring::quote());
17});

To demonstrate the ease of with which new commands can be defined, the following can be added to the console.php to register a new, interactive command:

1 
2// ...
3 
4Artisan::command('say:hello {name}', function($name) {
5 $favoriteSnack = $this->ask('What is your favorite snack?');
6 
7 $this->info(
8 "Hello, {$name}. Your favorite snack is {$favoriteSnack}!"
9 );
10})->describe('Give a warm welcome.');

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.