Paulund
2017-08-25 #laravel

Creating Your Own Artisan Commands

Command line scripts can be a big benefit to your application, they're a great way to automate certain tasks or make it easy to get your application up and running quickly. Maybe you have a create test database script that will create your sqlite database file, run migrations and seed the database ready to run your tests. To use console scripts in Laravel it uses a library called artisan, Laravel ships with a nice collection of pre-built commands to help make your application easier to developers. To see a list of the Artisan commands you can use the command.


php artisan list

Which will output all the available commands. The below list is the list of command as of Laravel 5.4.


Available commands:
  clear-compiled       Remove the compiled class file
  down                 Put the application into maintenance mode
  env                  Display the current framework environment
  help                 Displays help for a command
  inspire              Display an inspiring quote
  list                 Lists commands
  migrate              Run the database migrations
  optimize             Optimize the framework for better performance
  serve                Serve the application on the PHP development server
  tinker               Interact with your application
  up                   Bring the application out of maintenance mode
 app
  app:name             Set the application namespace
 auth
  auth:clear-resets    Flush expired password reset tokens
 cache
  cache:clear          Flush the application cache
  cache:forget         Remove an item from the cache
  cache:table          Create a migration for the cache database table
 config
  config:cache         Create a cache file for faster configuration loading
  config:clear         Remove the configuration cache file
 db
  db:seed              Seed the database with records
 event
  event:generate       Generate the missing events and listeners based on registration
 key
  key:generate         Set the application key
 make
  make:auth            Scaffold basic login and registration views and routes
  make:command         Create a new Artisan command
  make:controller      Create a new controller class
  make:event           Create a new event class
  make:job             Create a new job class
  make:listener        Create a new event listener class
  make:mail            Create a new email class
  make:middleware      Create a new middleware class
  make:migration       Create a new migration file
  make:model           Create a new Eloquent model class
  make:notification    Create a new notification class
  make:policy          Create a new policy class
  make:provider        Create a new service provider class
  make:request         Create a new form request class
  make:seeder          Create a new seeder class
  make:test            Create a new test class
 migrate
  migrate:install      Create the migration repository
  migrate:refresh      Reset and re-run all migrations
  migrate:reset        Rollback all database migrations
  migrate:rollback     Rollback the last database migration
  migrate:status       Show the status of each migration
 notifications
  notifications:table  Create a migration for the notifications table
 passport
  passport:client      Create a client for issuing access tokens
  passport:install     Run the commands necessary to prepare Passport for use
  passport:keys        Create the encryption keys for API authentication
 queue
  queue:failed         List all of the failed queue jobs
  queue:failed-table   Create a migration for the failed queue jobs database table
  queue:flush          Flush all of the failed queue jobs
  queue:forget         Delete a failed queue job
  queue:listen         Listen to a given queue
  queue:restart        Restart queue worker daemons after their current job
  queue:retry          Retry a failed queue job
  queue:table          Create a migration for the queue jobs database table
  queue:work           Start processing jobs on the queue as a daemon
 route
  route:cache          Create a route cache file for faster route registration
  route:clear          Remove the route cache file
  route:list           List all registered routes
 schedule
  schedule:run         Run the scheduled commands
 scout
  scout:flush          Flush all of the model's records from the index
  scout:import         Import the given model into the search index
 session
  session:table        Create a migration for the session database table
 storage
  storage:link         Create a symbolic link from "public/storage" to "storage/app/public"
 vendor
  vendor:publish       Publish any publishable assets from vendor packages
 view
  view:clear           Clear all compiled view files

In this tutorial we're going to learn how to create our own Artisan commands. ## Generate Artisan Command

In the list above you may notice there's an Artisan command of make which has a sub-list attached to it which allows you to make new Artisan commands, therefore we can use the command.


php artisan make:command TestCommand

This will create a new file inside app/Console/Commands called TestCommand.php.


namespace App\Console\Commands;

use Illuminate\Console\Command;

class TestCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * 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()
    {
        //
    }
}

As you can see it creates a class with two properties, $signature and $description. $signature is used to define the command to use. $description is to describe the command. There's a __construct function that you can use to inject any dependencies of your command. The handle method is where you put the code to run when the command is called.

Registering Your Command

After your command has been created you need to register it in the kernel so that artisan can access the command. To do this open up the console Kernel file app/Console/Kernel.php, you'll notice there is a $commands property which is an array of commands that are registered to use in artisan.


/**
  * The Artisan commands provided by your application.
  *
  * @var array
  */
  protected $commands = [
      TestCommand::class
  ];

Command Arguments

You might want to add additional arguments to your command, you can do so by adding them to the signature of the command. For example if we were building a command to search for the users in the database and output that row then we'll want to add an argument of the user email we can use to search on.


/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'user:search {email}';

Now if you run the user:search command you'll be prompted to supply an email argument. So that we can replace the command with something that has the email argument php artisan user:search [email protected]. If you want to make the argument optional you can do so by adding a question mark at the end of the argument.


/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'user:search {email?}';

Options

Like arguments you can also allow your command to accept options. These differ to arguments by the way that the arguments will accept a value while options are like flags which you turn on. For example you could add an output option which when is turned on the user will output. To add an option to your command you add the option into the signature just like argument.


/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'user:search {email} {--output}';

Options are optional flags so you don't always have to have them in the command but they should be used to turn on certain parts of the script. ## Retrieving Input

We've learnt how you can add inputs into your script but now we need to pick them up in the script so we can change the actions of the script. To access an argument in the script you can either use arguments() or argument().


$all = $this->arguments();

To get a specific argument.


$email = $this->argument('email');

To collect the options from the command you need to use options() and option().


$all = $this->options();

To get a specific argument.


$output = $this->option('output');

Prompt Inputs

Using arguments and options is a good way of making the user of the command pass in values or flag certain features of the script. Another way of getting important information from the user is to prompt them for a value. In the above example we used an argument to get the user email address we can use to search on, instead of having an argument we can add a prompt to get the email address.


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $email = $this->ask('What is the user\'s email address?');

        $this->line($email);
    }

When you ask the user a question as they type the answer it is output on the screen, if you're asking for something like a password you don't want this output as they type so you can use the function secret instead of ask.


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $password = $this->secret('What is your password?');

        $this->line($password);
    }

Asking For Confirmation

Instead of using options you could ask the user for a confirmation. For example the above code will ask for the user password and output the password on the screen. What if we don't the password to be output on the screen we can ask the user if they want to see the password typed in, and we can do this by asking the user.


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $password = $this->secret('What is your password?');

        if($this->confirm('Do you want to output the password?'))
        {
            $this->line($password);
        }
    }

Now when we run the query we will first be asked for the password.


What is your password?:
 > 

Then we will be asked if we want to output the typed in password.


 Do you want to output the password? (yes/no) [no]:
 >

If the user writes no, nothing is output, if the user types yes then the password will be output back to them.

Writing Output

To output information to the user inside your scripts you can use multiple methods of, line, info, comment, question and error. The difference between these methods is the output styling. Line will output in plain white text on the command line. Info will output text as green text. Comment will output as yellow text. Question will output in black text with a blue highlight. Error will output in white text with a red highlight.

Output As A Table

Another approach to take with with outputting on the command line is to output a table, therefore in our example of getting a user by email we can then query the database and return the data in a table.


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $user = User::where('email', $email)->first();

        $headers = [
            'id', 'name', 'email'
        ];
        
        $this->table($headers, [$user->pluck('id', 'name', 'email')->toArray()]);
    }

This will output the user information within a table.


+----+-------+--------------------+
| id | name  | email              |
+----+-------+--------------------+
| 1  | Admin | [email protected] |
+----+-------+--------------------+