December 7, 2016 —John Koster
The typical Artisan command development workflow involves writing commands that interact with different components of the application or external services; the commands themselves are usually isolated in their scope and generally do not depend on other commands or operating system calls. However, it can be incredibly useful to interact with other Artisan commands and operating system features to create more robust commands or to automate different actions throughout the application.
Laravel's Illuminate\Console\Command
base class provides useful methods for interoping with other Artisan commands: the call($command, array $arguments = [])
and callSilent($command, array $arguments = [])
methods. Both methods accept the name of the Artisan command to call (via an argument supplied to the $command
parameter) and an optional array of $arguments
that should be passed to the Artisan command.
Both commands can be used to call other Artisan commands and return the exit code from the command:
1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6 7class ExampleCommand extends Command 8{ 9 10 // ...11 12 public function handle()13 {14 // Call the `migrate` command from15 // within the ExampleCommand.16 $exitCode = $this->call('migrate');17 }18 19 // ...20 21}
The previous code example would execute the migrate
Artisan command whenever the ExampleCommand
executes. It is also possible to supply arguments and options to the commands that are called via the $arguments
parameter. Options and arguments are supplied via an array. The argument and option names should be the key of the array element and the desired value should be the element's value.
The following example would call the migrate
command while supplying options and arguments to the command:
1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6 7class ExampleCommand extends Command 8{ 9 10 // ...11 12 public function handle()13 {14 // Call the `migrate` command from15 // the ExampleCommand with options.16 $exitCode = $this->call('migrate', [17 '--force' => true,18 '--path' => database_path('tenant_migrations')19 ]);20 }21 22 // ...23 24}
In the previous example, the ExampleCommand
is calling the migrate
Artisan command with the --force
option flag and the --path
option with a string value. For options that act as a flag, or do not accept a value, simply supply a truth value of either true
or false
as the value of the option (the --force
option flag is an example of this).
It is important to note that, because of the way that command strings are internally constructed, it is still required to prefix command options with hyphens (--
, or -
for option shortcuts). Failing to due so will either supply a value to a similarly named argument or cause the command to throw a fatal exception.
Any output that is generated by called Artisan commands will still be displayed to the user executing the parent command when using the call
method. To hide any output from other Artisan commands, simply use the callSilent
method to execute the command without displaying any output from that command:
1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6 7class ExampleCommand extends Command 8{ 9 10 // ...11 12 public function handle()13 {14 // Call the `migrate` command from15 // the ExampleCommand with options.16 $exitCode = $this->callSilent('migrate', [17 '--force' => true,18 '--path' => database_path('tenant_migrations')19 ]);20 }21 22 // ...23 24}
The call
and callSilent
commands discussed in the previous section are defined as part of the Artisan Command
base class, which is not incredibly useful when commands need to be executed from other locations within the application's code base. Luckily, the console kernel (Illuminate\Foundation\Console\Kernel
) exposes a call($command, array $parameters = [])
method that can be used to execute commands from arbitrary locations within the application's code base.
The following example demonstrates how to call an Artisan command from a controller by injecting the console kernel:
1<?php 2 3namespace App\Http\Controllers; 4 5use App\Console\Kernel; 6 7class ExampleController extends Controller 8{ 9 10 protected $artisan;11 12 public function __construct(Kernel $artisan)13 {14 $this->artisan = $artisan;15 }16 17 public function getIndex()18 {19 // Call an Artisan command from20 // inside the controller.21 $this->artisan->call('migrate', [22 '--force' => true,23 '--path' => database_path('tenant_migrations')24 ]);25 }26 27}
It is also possible to call Artisan commands using the Artisan
command:
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Support\Facades\Artisan; 6 7class ExampleController extends Controller 8{ 9 10 public function getIndex()11 {12 // Call an Artisan command from13 // inside the controller using14 // the Artisan facade.15 Artisan::call('migrate', [16 '--force' => true,17 '--path' => database_path('tenant_migrations')18 ]);19 }20 21}
It is also possible to make operating system calls or interact directly with third-party systems using Symfony's Process component. While PHP provides its own features for making operating system calls, the Symfony component is capable of dealing with the nuances and differences between different operating system environments. Because Laravel already depends on the Process component, it does not have to be explicitly loaded using Composer, and is already available for use.
The following code example demonstrates how the Process component works for calling basic operating system features:
1<?php 2 3use Symfony\Component\Process\Process; 4 5// Create the process. 6$process = new Process('composer dump-autoload -o'); 7 8// Start the process. 9$process->run();10 11// Determine if the process failed.12if (!$process->isSuccessful()) {13 // Handle process failure.14}
When using Symfony's Process component to interact with third-party systems and to make calls to operating system features it may be required to retrieve the output from the process. A simple and effective way to retrieve real-time output from the process is to supply a callback to the process's run
method.
The following code example demonstrates how to retrieve real-time output from a Symfony process and display it in the context of a Laravel command:
1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6use Symfony\Component\Process\Process; 7 8class ExampleCommand extends Command 9{10 11 // ...12 13 public function handle()14 {15 // Call the `phpunit` library.16 $process = new Process('phpunit');17 18 // Run the process while streaming19 // the output to the appropriate20 // output channels, using the21 // Laravel command methods.22 $exitCode = $process->run(function ($type, $buffer) {23 if (Process::ERR === $type) {24 // Write process error output to command output.25 $this->error($buffer);26 } else {27 // Write process standard output to command info output.28 $this->info($buffer);29 }30 });31 }32 33 // ...34 35}
∎
The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.