How to create custom Artisan commands in a Laravel 11 application
Exploring the creation of custom Artisan commands in a Laravel application
Introduction
In this article, we'll be looking at how to create custom commands in a Laravel 11 application to perform customized or defined actions through the command line or scheduler.
A command is simply an instruction that is given the ability to perform a task.
The need to perform certain task behind the scene is a requirement for certain apps to function effectively and efficiently.
For instance, if you want to pull certain records from an endpoint to prepopulate a table in a database or display records within an application the custom command feature comes into play. This is helpful because you won't have the need to request for such service at every instance.
Benefits of writing Laravel commands
Remove the workload of manually repeating tasks based on conditions on production applications.
It can be used to set up an application ( for instance we can run a command that asks the user the name of the database, type of connection, user_name etc from the artisan console).
Can be used to perform a large task that requires more execution time to be accomplished.
It's helpful during the development process of an application where some activities can be performed from the command even without interacting with the browser.
Artisan Console
The Laravel commands are executed via the Artisan console.
Artisan is the command-line interface included with Laravel. Artisan exists at the root of your application as the artisan script and provides a number of helpful commands that can assist you while you build your application.
Examples of Laravel Artisan commands
- php artisan serve (serves the application )
Laravel commands can also accept arguments or parameters
if the --port parameter is added it serves the application on a specific port
php artisan serve --port=8002 serves the application on 127.0.0.1:8002
- php artisan migrate
creates tables for the application.
- php artisan make:controller PostController
creates a controller with the name PostController
And so many examples of in-build commands in Laravel
In order to keep this article simple, I'll be using this Laravel blog application to demonstrate how to publish a blog post from the command line with options (flags).
How Create a Custom Command
The Laravel Artisan make:command is used to create custom commands in Laravel.
php artisan make:command
We'll create a command to create a blog post to demo how it works. The essence of this command is to create a blog post.
php artisan make:command CreateBlogPost
All the custom commands created can be found in the app/Console/Commands folder.
The CreateBlogPost command class
Laravel goes ahead and sets the name, description, and parameters on the console commands just to make things a little easier on the developer. This is so they don't have to all be manually specified in the constructors.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CreateBlogPost extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:create-blog-post';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle()
{
//
}
}
Let's update this command to create a blog post for this application
The signature (the name of the command)
protected $signature = 'blog:create-post';
The command description (this is important for clarity purposes in a case where the name might not be sufficient to convey the meaning in the future or to another developer )
protected $description = 'A command to create a post for this blogging application';
There are other protected parameters such as:
$help (The console command help text)
$hidden (Indicates whether the command should be shown in the Artisan command list.)
View List of Commands
To view the list of commands
php artisan list
Hide Command From Artisan List
To hide the command set hidden to true, probably for security reasons ....
protected $hidden = true;
Run the artisan list command
php artisan list
Update the Handle Method
The handle method is the method that gets executed when the custom command is triggered either by a scheduler or through a command line interface.
public function handle()
{
//creates a blog post for a user
Post::create([
'title' => Str::random(10),
'content' => Str::random(10),
'user_id' => 1
]);
//logs the message on the console.
$this->info('Blog post created successfully!!!');
//log an error to the user
// $this->error('Something went wrong!');
}
Next
Run the create blog post command
php artisan blog:create-post
Defining Arguments for Custom Commands
In a case where we need the title, content, user_id etc to be defined with the command as arguments?
Arguments
- For example: php artisan blog:create-post title="Laravel commands" --content="How to create laravel commands"
Let's update the signature and the handle method
protected $signature = 'blog:create-post {title} {description} {user_id}';
protected $signature = 'blog:create-post {title} {description?} {user_id?}';
- handle method
public function handle()
{
$title = $this->argument('title');
$description = $this->argument('description');
$user_id = $this->argument('user_id');
//can use $this->arguments() to retrieve input
Post::create([
'title' => $title ?? Str::random(10),
'content' => $content ?? Str::random(10),
/**cast the user_id to int since the input comes as string**/
'user_id' => (int)$user_id ?? 3
]);
$this->info('Blog post created successfully');
}
Options
Options are prefixed by two hyphens (--
) when they are provided via the command line. There are two types of options: those that receive a value and those that don't. Options that don't receive a value serve as a boolean "switch".
Another example with flag: php artisan blog:create-post --title="Laravel commands" --description="How to create laravel commands"
- Update the signature
protected $signature = 'blog:create-post {--title=} {--description=} {--user_id=}';
- update handle method
public function handle()
{
$title = $this->option('title');
$description = $this->option('description');
$user_id = $this->option('user_id');
//can use $this->options() to retrieve all input
Post::create([
'title' => $title ?? Str::random(10),
'content' => $content ?? Str::random(10),
'user_id' => (int)$user_id ?? 3
]);
$this->info('Blog post created successfully');
}
The parameters can be passed in with no particular order.
Custom Commands with Progress Bar
A progress bar can be displayed in the Artisan console when a task is running.
Let's specify how many blog post to create from the command line
- update the $signature
protected $signature = 'blog:create-post {--number_of_posts=}';
- update the handle method
public function handle()
{
$number_of_posts = (int) $this->option('number_of_posts');
$bar = $this->output->createProgressBar($number_of_posts);
$bar->start();
for ($i=1; $i <= $number_of_posts; $i++) {
//creates a blog post for a user
Post::create([
'title' => Str::random(10),
'content' => Str::random(10),
'user_id' => 3
]);
$bar->advance();
}
$bar->finish();
$this->info(' '. $number_of_posts . ' blog posts created successfully with progress bar!!!');
}
Run the command to try the progress bar
php artisan blog:create-post --number_of_posts=10
To keep an input secret
$password = $this->secret('What is the password?');
You can ask for a question
$feedback = $this->ask('Do you like my blog application?', 'Yes');
Confirmation
//default value of true
if ($this->confirm('Do you wish to continue?', true)) {
// ...
}
Auto-completion using the anticipate method
$title= $this->anticipate('What is your blog title?', ['Laravel 11', 'Laravel Blog']);
- Multiple Choice Questions
If you need to give the user a predefined set of choices when asking a question, you may use the choice
method.
In addition, the choice
method accepts optional fourth and fifth arguments for determining the maximum number of attempts to select a valid response and whether multiple selections are permitted:
$feedback = $this->choice(
'What is your best format for tutorial?',
['Video', 'Article', 'Podcast'],
$defaultIndex
$maxAttempts = null,
$allowMultipleSelections = false
);
Registering Commands in Laravel
Open the bootstrap/app.php to register any command.
//the createblog post gets imported at the top
})->withCommands([
CreateBlogPost::class
])->create();
Artisan commands can be called, queued etc.....
Conclusion
We've covered beyond basics of custom commands in Laravel application.
You can look into the Artisan Command in the Laravel documentation for other options to explore for custom commands and how to register them.
How about if these commands are needed to be executed at intervals ( every minute, hourly, daily, weekly, monthly etc..) or are we going to always run the commands individually for the application? That's where the scheduler comes into play. With the help of cron jobs, these commands can be executed on the server at the configured intervals which we'll be looking at in subsequent articles.
If you find this article useful please kindly share it with your network and feel free to use the comment section for questions, answers, and contributions.