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.

Executing Commands From Other Artisan Commands

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:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ExampleCommand extends Command
{

    // ...

    public function handle()
    {
        // Call the `migrate` command from
        // within the ExampleCommand.
        $exitCode = $this->call('migrate');
    }

    // ...

}

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:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ExampleCommand extends Command
{

    // ...

    public function handle()
    {
        // Call the `migrate` command from
        // the ExampleCommand with options.
        $exitCode = $this->call('migrate', [
            '--force' => true,
            '--path'  => database_path('tenant_migrations')
        ]);
    }

    // ...

}

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:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class ExampleCommand extends Command
{

    // ...

    public function handle()
    {
        // Call the `migrate` command from
        // the ExampleCommand with options.
        $exitCode = $this->callSilent('migrate', [
            '--force' => true,
            '--path'  => database_path('tenant_migrations')
        ]);
    }

    // ...

}

Calling Commands From Application Code

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:

<?php

namespace App\Http\Controllers;

use App\Console\Kernel;

class ExampleController extends Controller
{

    protected $artisan;

    public function __construct(Kernel $artisan)
    {
        $this->artisan = $artisan;
    }

    public function getIndex()
    {
        // Call an Artisan command from
        // inside the controller.
        $this->artisan->call('migrate', [
            '--force' => true,
            '--path'  => database_path('tenant_migrations')
        ]);
    }

}

It is also possible to call Artisan commands using the Artisan command:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Artisan;

class ExampleController extends Controller
{

    public function getIndex()
    {
        // Call an Artisan command from
        // inside the controller using
        // the Artisan facade.
        Artisan::call('migrate', [
            '--force' => true,
            '--path'  => database_path('tenant_migrations')
        ]);
    }

}

Operating System Calls

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:

<?php

use Symfony\Component\Process\Process;

// Create the process.
$process = new Process('composer dump-autoload -o');

// Start the process.
$process->run();

// Determine if the process failed.
if (!$process->isSuccessful()) {
    // Handle process failure.
}

Handling Process Output

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:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Symfony\Component\Process\Process;

class ExampleCommand extends Command
{

    // ...

    public function handle()
    {
        // Call the `phpunit` library.
        $process = new Process('phpunit');

        // Run the process while streaming
        // the output to the appropriate
        // output channels, using the
        // Laravel command methods.
        $exitCode = $process->run(function ($type, $buffer) {
            if (Process::ERR === $type) {
                // Write process error output to command output.
                $this->error($buffer);
            } else {
                // Write process standard output to command info output.
                $this->info($buffer);
            }
        });
    }

    // ...

}