Implementing Laravel Artisan Console Commands

4 min read

The first step to creating custom commands is to generate the basic structure, or scaffolding, for the new command. This can be done by issuing the make:console Artisan command from the terminal. The make:console command accepts the name of the new command class, as well as accepts an optional --command option that can be used to specify the terminal command name (for example, make:console is the terminal command name of the ConsoleMakeCommand class).

By default, custom Artisan commands are stored in the app/Console/Commands directory, and are namespaced under the App\Console\Commands namespace. The following command would create a new class called CreateFileCommand and set the terminal command name to create:file. The command scaffolding would be generated and saved to the app/Console/Commands/CreateFileCommand.php file.

1# Generate scaffolding for a new command.
2php artisan make:console CreateFileCommand --command=create:file

The generated scaffolding would look similar to the following output:

1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6 
7class CreateFileCommand extends Command
8{
9 /**
10 * The name and signature of the console command.
11 *
12 * @var string
13 */
14 protected $signature = 'create:file';
15 
16 /**
17 * The console command description.
18 *
19 * @var string
20 */
21 protected $description = 'Command description';
22 
23 /**
24 * Create a new command instance.
25 *
26 * @return void
27 */
28 public function __construct()
29 {
30 parent::__construct();
31 }
32 
33 /**
34 * Execute the console command.
35 *
36 * @return mixed
37 */
38 public function handle()
39 {
40 //
41 }
42}

As can be seen in the above output, each command contains a $signature and $description property. The $signature property is used to specify what arguments and options the command can accept (this property did not exist in Laravel versions prior to version 5.1; options and arguments used to be defined using the getOptions and getArguments methods). The $description property can be used to provide a description for the newly generated command.

Just because the command has been generated, does not mean it is available for use within the Artisan console application. If the following was executed:

1php artisan create:file

an error similar to the following would be generated and displayed as output:

1There are no commands defined in the "create" namespace.

In order for the command to be available, it needs to be registered with the application's console kernel (located in the app/Console/Kernel.php file). The following can be added to the $commands property within the Kernel.php file to register the newly generated command (only the $commands property is being shown here):

1<?php
2 
3// ...
4 
5protected $commands = [
6 // ...
7 CreateFileCommand::class
8 // ...
9];

After saving the Kernel.php file, the create:file command should be available for use. If the command still cannot be found, regenerating Composer's class auto-loader file generally resolves the issue. To do this, simply issue the following command within the application's root directory:

1# Regenerate the Composer auto-loader file.
2composer dump-autoload -o

At this point, a simple CreateFileCommand command exists, but does not accomplish anything. When a command is executed from the terminal, or elsewhere, its handle method is ultimately called. It is within the handle method that the command's logic should be placed, even if it is to make calls to other libraries or services.

The following handle method implementation would simply create a new file with the current time inside a custom directory in the applications storage directory:

1<?php
2 
3// ...
4 
5public function handle()
6{
7 // Create a new file with the current time as the name.
8 touch(storage_path('create_file/'.time()));
9}

The above example references a directory that is not included in the application storage directory by default. The create_file directory must be created manually before attempting to execute the example command or else an error stating something similar to "Unable to create file because no such file or directory exists" will be issued.

Each time the CreateFileCommand command is called, a new file will be created inside the app/storage/create_file directory.

Thanks for taking the time to read this post! If you found this article useful and want to help support more work like this, please consider sponsoring my work on GitHub, or by checking out some merch.

 Sponsor on GitHub  Shop Merch