Igor Timoshenko
Igor Timoshenko

Reputation: 1011

Calling console command within command and get the output in Symfony2

I have a few console command in Symfony2 and I need to execute one command from another command with some parameters.

After successfull execution of the second command I need to get the result (as an array for example), not the display output.

How can I do that?

Upvotes: 18

Views: 18858

Answers (6)

perfectcu.be
perfectcu.be

Reputation: 11

As an update for Onema's answer, in Symfony 3.4.x (used by Drupal 8),

  1. you also need to set setAutoExit(false),
  2. and the command returns an int(0) if successful.

Here's the updated example that I'm using to script composer commands in php for a Drupal 8.8 project. This gets a list of all composer packages as json, then decodes that into a php object.

<?php 

require __DIR__.'/vendor/autoload.php';

use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Composer\Console\Application;

$input = new ArrayInput([
  'command' => 'show', 
  '--format'=>'json',
]);

$output = new BufferedOutput();
$application = new Application();

// required to use BufferedOutput()
$application->setAutoExit(false);
// composer package list, formatted as json, will be barfed into $output 
$status = $application->run($input, $output);
if($status === 0) {
  // grab the output from the $output buffer
  $json = $output->fetch();
  // decode the json string into an object
  $list = json_decode($json);
  // Profit!
  print_r($list);
}

?>

The output will be something like this:

stdClass Object
(
    [installed] => Array
        (
            ... omitted ...

            [91] => stdClass Object
                (
                    [name] => drupal/core
                    [version] => 8.9.12
                    [description] => Drupal is an open source content management platform powering millions of websites and applications.
                )
            ... omitted ...
        )

)

With the help of Onema's hint Google found the rest of the solution for me here.

Upvotes: 1

Webghost
Webghost

Reputation: 933

I understand it's old post and above answers solves the problem with a bit of digging. In Symfony2.7, I had a bit issue making it work, so with above suggestions, I dug a little and have compiled the full answer here. Hope it will be useful for someone.

Using Console command under console command

Upvotes: 0

Onema
Onema

Reputation: 7582

There is an new Output class (as of v2.4.0) called BufferedOutput.

This is a very simple class that will return and clear the buffered output when the method fetch is called:

    $output = new BufferedOutput();
    $input = new ArrayInput($arguments);
    $code = $command->run($input, $output);

    if($code == 0) {
        $outputText = $output->fetch();
        echo $outputText;
    } 

Upvotes: 12

iBet7o
iBet7o

Reputation: 778

I did the following

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;

$tmpFile = tmpfile();
$output  = new StreamOutput($tmpFile);
$input   = new ArrayInput(array(
    'parameter' => 'value',
));

$command = . . .
$command->run($input, $output);

fseek($tmpFile, 0);
$output = fread($tmpFile, 1024);
fclose($tmpFile);

echo $output;

¡it works!

Upvotes: 3

Fnayou
Fnayou

Reputation: 422

you have to pass the command in the arguments array, and to avoid the confirmation dialog in doctrine:fixtures:load you have to pass --append and not --force

    $arguments = array(
    'command' => 'doctrine:fixtures:load',
    //'--append' => true
    ''
);

or it will fail with error message “Not enough arguments.”

Upvotes: 22

j0k
j0k

Reputation: 22756

Here you can have a basic command inside a command. The output from the second command can be a json, then you just have to decode the output json to retrieve your array.

$command = $this->getApplication()->find('doctrine:fixtures:load');
$arguments = array(
    //'--force' => true
    ''
);
$input = new ArrayInput($arguments);
$returnCode = $command->run($input, $output);

if($returnCode != 0) {
    $text .= 'fixtures successfully loaded ...';
    $output = json_decode(rtrim($output));
}

Upvotes: 26

Related Questions