How to create custom Artisan commands in a Laravel 11 application

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).

💡
You can watch how to build a blog application using Laravel 11 on my Youtube channel

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

image.png

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

image.png

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

image.png

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

image.png

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}';
💡
Add the ? to make any parameter optional and must come after the required parameter.

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');
    }

image.png

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.

image.png

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

image.png

image.png

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.

💡
Note: Please ensure to always secure or validate the header request of the commands and don't run them from the routes except if you have some sort of middleware to validate the request type if possible with a token.

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.

💡
Follow me on Hashnode: Alemsbaja --- X: Alemsbaja ---- Youtube: Tech with Alemsbaja to stay updated on more articles

Did you find this article valuable?

Support Alemoh Rapheal Baja by becoming a sponsor. Any amount is appreciated!