2

I have a Symfony2 Console application with a few commands:

$application = new Application();

$application->add(new MyCommand1());
$application->add(new MyCommand2());

$application->run();

When running the application, I'd like the output to be redirected both to the console and to a file.

I can use StreamOutput for this, but it looks like I can only provide such an output object if I manually run one of the commands:

$input = ...;
$output = new StreamOutput(fopen('output.log', 'a'));

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

But this is not what I want.

Is it possible to add a secondary output to the Application itself? So that all commands output both to the console, and to a file.

1
  • you can use monolog to do that Commented Sep 24, 2013 at 9:35

1 Answer 1

3

To achieve this task, I would create my own Output.

class MultipleOutput implements OutputInterface
{
    protected $outputs = array();

    public function __construct(array $outputs = array())
    {
        $this->setOutputs($outputs);
    }

    public function setOutputs(array $outputs = array())
    {
        foreach ($outputs as $output) {
            $this->addOutput($outputs);
        }
    }

    public function addOutput(OutputInterface $output)
    {
        $this->outputs[] = $output;
    }

    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        foreach ($this->outputs as $output) {
            $output->write($messages, $newline, $type);
        }
    }

    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        foreach ($this->outputs as $output) {
            $output->writeln($messages, $type);
        }
    }

    public function setVerbosity($level)
    {
        foreach ($this->outputs as $output) {
            $output->setVerbosity($level);
        }
    }

    /**
     * Returns only the first one
     */
    public function getVerbosity()
    {
        foreach ($this->outputs as $output) {
            return $output->getVerbosity();
        }
    }

    public function setDecorated($decorated)
    {
        foreach ($this->outputs as $output) {
            $output->setDecorated($decorated);
        }
    }

    /**
     * Returns only the first one
     */
    public function isDecorated()
    {
        foreach ($this->outputs as $output) {
            return $output->isDecorated();
        }
    }

    public function setFormatter(OutputFormatterInterface $formatter)
    {
        foreach ($this->outputs as $output) {
            $output->setFormatter($formatter);
        }
    }

    /**
     * Returns only the first one
     */
    public function getFormatter()
    {
        foreach ($this->outputs as $output) {
            return $output->getFormatter();
        }
    }
}

Then you can use it in your application

$application = new Application();

$application->add(new MyCommand1());
$application->add(new MyCommand2());

$output = new MultipleOutput(array(new StreamOutput, new ConsoleOutput));

$application->run(new ArgvInput, $output);
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I missed the fact that you could actually pass an Output to Application::run()!
This MultipleOutput would probably be useful in Symfony by the way, what about a pull request?
@Benjamin I might give a try sooner or later!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.