Use Artisan to build powerful console applications


brief introduction

Artisan is the command line interface provided by Laravel, which provides us with many useful commands in the development process. To view all available Artisan commands, use the list Command:

 php artisan list

Each command can be used help The command displays the command description and command parameters and options. To view the help interface, just add help You can:

 php artisan help migrate

Laravel REPL

All Larravel applications provide Tinker, a PsySH The expansion pack driven REPL (Read Eval Print Loop, that is, the terminal command line "read evaluate output" cycle tool). Tinker allows you to interact with the entire Laravel application through the command line, including Eloquent ORM, tasks, events, and so on. To enter the Tinker environment, run tinker Command:

 php artisan tinker
Note: Please refer to this tutorial for the use of Tinker Use Php Artisan Tinker to debug your Laravel

Write Command

In addition to the system commands provided by Artisan, you can also write your own commands. Custom commands are usually stored in app/Console/Commands Directory; Of course, you can also choose your own storage location, as long as the command class can be automatically loaded by Composer.

Generate Command

To create a new command, you can use the Artisan command make:command , the command will app/Console/Commands Create a new command class under the directory. If the directory does not exist, don't worry, it will run Artisan command for the first time make:command Is created when. The generated command will contain default property settings and methods common to all commands:

 php artisan make:command SendEmails

Command structure

After the command is generated, you need to fill in the signature and description Property. These two properties are called list It will be used when displaying commands. handle Method is called when the command is executed. You can put all the command logic in this method.

Note: In order to better realize code reuse, the best practice is to keep the console commands lightweight and let them delay to the application service to complete the task. In the following example, we have injected a service class to complete such "heavy" tasks as sending emails.

Let's take a look at an example. Note that we can inject any dependency into the constructor of the command class Service Container All dependent type prompts will be automatically injected into the constructor:

 <? php namespace App\Console\Commands; use App\User; use App\DripEmailer; use Illuminate\Console\Command; class SendEmails extends Command { /** * The name and signature of the console command. * * @var string * @translator laravelacademy.org */ protected $signature = 'email:send {user}'; /** * The console command description. * * @var string */ protected $description = 'Send drip e-mails to a user'; /** * The drip e-mail service. * * @var DripEmailer */ protected $drip; /** * Create a new command instance. * * @param  DripEmailer  $drip * @return void */ public function __construct(DripEmailer $drip) { parent::__construct(); $this->drip = $drip; } /** * Execute the console command. * * @return mixed */ public function handle() { $this->drip->send(User::find($this->argument('user'))); } }

Closure command

Closure based commands, like closure routing for controllers, provide an optional solution for defining console commands in a class way app/Console/Kernel.php Filed commands Method, Larravel loads the routes/console.php File:

 /** *Register closure based commands for applications * * @return void */ protected function commands() { require base_path('routes/console.php'); }

Although this file does not define HTTP routing, it defines the console based application portal (the same as routing). In this file, you can use Artisan::command Method defines all closure based routes. command Method receives two parameters—— Command ID And closures that receive command parameters and options:

 Artisan::command('build {project}', function ($project) { $this->info("Building {$project}!"); });

This closure is bound to the underlying command instance, so you can access all auxiliary methods as in the complete command class.

Copy the above code to routes/console.php The file can be called at the terminal:

Type hint dependency

In addition to receiving command parameters and options, closure commands can also type prompts Service Container Additional dependencies for external resolution:

 use App\User; use App\DripEmailer; Artisan::command('email:send {user}', function (DripEmailer $drip, $user) { $drip->send(User::find($user)); });

Closure Command Description

When defining closure based commands, you can use the describe Method to add a command description, which will be run php artisan list or php artisan help When command:

 Artisan::command('build {project}', function ($project) { $this->info("Building {$project}!"); })->describe('Build the project');

Define expected input

When writing console commands, user input is usually collected through parameters and options. Laravel makes this operation convenient: use in commands signature Property to define the user input we expect. signature Properties allow you to define command names, parameters, and options through an elegant, routing style syntax.

parameter

All parameters and options provided by the user are enclosed in curly braces. The command defined in the following example requires user input Mandatory parameter user

 /** *Console Command Name * * @var string */ protected $signature = 'email:send {user}';

You can also make this parameter optional and define the default optional parameter values:

 //Option Parameters email:send {user?} //Option parameters with default values email:send {user=foo}

option

Options, like parameters, are another form of user input. The difference is that options are preceded by two dashes( -- ), there are two types of options: receive value and do not receive value. Options that do not receive values are typically used as Boolean switches. Let's look at an option of this type:

 /** *Console Command Name * * @var string */ protected $signature = 'email:send {user} {--queue}';

In this example, --queue The switch is specified when the Artisan command is called. If --queue Is passed, and the corresponding switch value is true , otherwise its value is false

 php artisan email:send 1 --queue

Options with values

Next, let's look at an option with a value. If the user has to specify a value for the option, you need to use the = To assign:

 /** *Console Command Name * * @var string */ protected $signature = 'email:send {user} {--queue=}';

In this example, the user can pass values in this way:

 php artisan email:send 1 --queue=default

You can also assign a default value to an option. If the user does not pass a value to an option, the default value will be used:

 email:send {user} {--queue=default}

Option Abbreviation

If you want to assign a abbreviation to a command option, you can specify and use a separator before the option | Separate shorthand and full option names:

 email:send {user} {--Q|queue}

Input array

If you want to define parameters and options to specify the input array, you can use characters * First, let's look at an example of specifying array parameters:

 email:send {user*}

When this method is called, user Parameters will be passed to the command line in sequence. For example, the following command will set user The value of is ['foo', 'bar']

 php artisan email:send foo bar

When defining an option of the expected input array, each option value passed to the command should be prefixed with the option name:

 email:send {user} {--id=*} php artisan email:send --id=1 --id=2

Enter Description

You can assign descriptions to input parameters and options by separating parameters and descriptions with colons. If you need some space to define commands, you can define commands by wrapping lines:

 /** *Console Command Name * * @var string * @translator laravelacademy.org */ protected $signature = 'email:send {user : The ID of the user} {--queue= : Whether the job should be queued}';

Command I/O

Get input

When the command is executed, it is obvious that you need to access the parameters and option values obtained by the command. use argument and option The method can achieve:

 /** *Execute the console command * * @return mixed */ public function handle() { $userId = $this->argument('user'); // }

If you need to return the values of all parameters in an array, call arguments method:

 $arguments = $this->arguments();

The option value is as simple as the parameter value option Method. To return all option values in an array, call options method:

 //Get Specified Options $queueName = $this->option('queue'); //Get All Options $options = $this->options();

If the parameter or option does not exist, return null

Input prompt

In addition to displaying the output, you may also want the user to provide input during command execution. ask The method will prompt the user with the given question, receive input, and then return to the command entered by the user:

 /** *Execute console commands * * @return mixed */ public function handle(){ $name = $this->ask('What is your name?'); }

secret Methods and ask The method is similar, but user input is invisible to them at the terminal. This method is useful when asking users for some sensitive information, such as passwords:

 $password = $this->secret('What is the password?');

Let the user confirm

If you need the user to confirm the information, you can use confirm Method. By default, this method returns false , if the user enters y , the method returns true

 if ($this->confirm('Do you wish to continue? [y|N]')) { // }

AutoComplete

anticipate The method can be used to provide automatic completion for possible options, and the user can still select the answer regardless of these choices:

 $name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);

Provide users with choices

If you need to give users predefined choices, you can use choice method. The user selects the index of the answer, but the answer value is returned to you. If the user does not select anything, you can set the default return value:

 $name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);

Write Output

To send output to the console, use the line , info , comment , question and error Method, each method will be identified with the corresponding ANSI color. For example, to display an information message to the user, use info The method is displayed in green on the terminal:

 /** *Execute console commands * * @return mixed */ public function handle(){ $this->info('Display this on the screen'); }

To display an error message, use the error method. The error message text is usually red:

 $this->error('Something went wrong!');

If you want to display native output, you can use line Method, which outputs characters without color:

 $this->line('Display this on the screen');

Table Layout

table The method makes it easy to output data in multi row/column format. You only need to pass the header and row to the method. The width and height will be automatically calculated based on the given data:

 $headers = ['Name', 'Email']; $users = App\User::all(['name', 'email'])->toArray(); $this->table($headers, $users);

The table layout output is as follows:

progress bar

For tasks that need to run for a long time, it is useful to display the progress indicator. Using this output object, we can start, advance, and stop the progress bar. At the beginning of the progress, you must define the number of steps, and then advance one grid for each step of the progress bar:

 Artisan::command('test', function () { $users = App\User::all(); $bar = $this->output->createProgressBar(count($users)); foreach ($users as $user) { //$this->performTask($user); sleep(3); //  Simulation task execution $bar->advance(); } $bar->finish(); $this->info('task finished!'); });

The progress bar output is as follows:

To learn more, see Symfony Progress Bar Component Document

Registration command

Because the Console Kernel commands Method will call load Methods, all app/Console/Commands The commands in the directory will be automatically registered through Artisan. In fact, you can call load Method to traverse Artisan commands in other directories:

 /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); $this->load(__DIR__.'/MoreCommands'); // ... }

In addition, you can also app/Console/Kernel.php Class $commands Property to register commands by manually adding class names. When Artisan starts, the commands listed in this attribute will be parsed by the service container and registered through Artisan:

 protected $commands = [ Commands\SendEmails::class ];

Calling commands through code

Sometimes you may want to execute Artisan commands outside the CLI, for example, you may want to trigger Artisan commands in the route or controller, which can be used Artisan On the facade call Method. call The method receives the name of the executed command as the first parameter, the command parameter array as the second parameter, and the exit code will be returned:

 Route::get('/foo', function () { $exitCode = Artisan::call('email:send', [ 'user' => 1, '--queue' => 'default' ]); });

use Artisan On the facade queue Method, you can even put Artisan commands into the queue, so that they can be processed by queue workers in the background. Before using this method, make sure you have configured the queue and run the queue listener:

 Route::get('/foo', function () { Artisan::queue('email:send', [ 'user' => 1, '--queue' => 'default' ]); });

You can also specify the connection or queue to which Artisan commands are distributed:

 Artisan::queue('email:send', [ 'user' => 1, '--queue' => 'default' ])->onConnection('redis')->onQueue('commands');

Passing array values

If the command defines the option to receive an array, you can pass the array value to this option:

 Route::get('/foo', function () { $exitCode = Artisan::call('email:send', [ 'user' => 1, '--id' => [5, 13] ]); });

Pass Boolean

If you need to specify the option value of not receiving strings, for example migrate:refresh On command --force Identification, Boolean value can be passed true or false

 $exitCode = Artisan::call('migrate:refresh', [ '--force' => true, ]);

Invoking commands through other commands

Sometimes you want to call other commands from an existing Artisan command. You can use call Method development achieves this goal. call Method receives command name and command parameters in array form:

 /** *Execute console commands * * @return mixed */ public function handle(){ $this->call('email:send', [ 'user' => 1, '--queue' => 'default' ]); }

If you want to invoke other console commands and block all their output, you can use callSilent method. callSilent Methods and call The method and usage are consistent:

 $this->callSilent('email:send', [ 'user' => 1, '--queue' => 'default' ]);

give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: Serialize model data into arrays or JSON

>>Next: Service decoupling through events and event listeners