tl;dr: I want to change an output formatter style across my entire Console application without having to modify every command. How can I make a single set of changes that take effect globally?
I want to globally change the error output formatter style in my Symfony 4 Console application. As per the documentation, it's easy to do so in an ad hoc fashion per command, e.g.:
public function execute(InputInterface $input, OutputInterface $output): int { $output->getFormatter()->setStyle('error', new OutputFormatterStyle('red'));}
But I don't want to add needless boilerplate to all my commands--especially not with a new
operator. For maintainability and testability, I prefer to override and inject my dependencies via the service container. I tried to do this by overriding the output formatter:
MyOutputFormatter.php
use Symfony\Component\Console\Formatter\OutputFormatter;use Symfony\Component\Console\Formatter\OutputFormatterStyle;class MyOutputFormatter extends OutputFormatter { public function __construct($decorated = FALSE, array $styles = []) { // I've tried it this way: $styles['error'] = new OutputFormatterStyle('red'); parent::__construct($decorated, $styles); // I've tried it this way: $this->setStyle('error', new OutputFormatterStyle('red')); // And I've tried it this way: $this->getStyle('error')->setForeground('red'); $this->getStyle('error')->setBackground(); }}
services.yml:
Symfony\Component\Console\Formatter\OutputFormatterInterface: alias: My\Console\Formatter\OutputFormatter
MyCommand.php
use Symfony\Component\Console\Command\Command;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Output\OutputInterface;class MyCommand extends Command { public function execute(InputInterface $input, OutputInterface $output) { $output->writeln("<error>I'm an error.</error>"); }}
But I must be doing something wrong, because although my class definitely gets injected and interpreted, whether I try to override an existing style or create a new one, it has no effect: I expect my custom style to be used (red foreground with no background), the default style is used instead (white foreground with a red background).
Can someone correct my misunderstanding or suggest a better way? Thanks!!