全局覆盖控制台样式的最简洁方法

Cleanest way to globally override a Console style

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?

我想在 my Symfony 4 Console application. As per the documentation 中全局更改错误输出格式化程序样式,每个命令以临时方式很容易做到这一点,例如:

public function execute(InputInterface $input, OutputInterface $output): int {
  $output->getFormatter()->setStyle('error', new OutputFormatterStyle('red'));
}

但我不想在所有命令中添加不必要的样板文件——尤其是使用 new 运算符时。为了可维护性和可测试性,我更喜欢通过服务容器覆盖和注入我的依赖项。我试图通过覆盖输出格式化程序来做到这一点:

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>");
  }

}

但我一定是做错了什么,因为虽然我的 class 肯定会被注入和解释,但无论我试图覆盖现有样式还是创建新样式,它都没有效果:我希望我的自定义要使用的样式(红色前景,无背景),则使用默认样式(白色前景,红色背景)。

有人可以纠正我的误解或提出更好的方法吗?谢谢!!

我解决了!结果非常简单:Application class 有一个 configureIO() 方法正是为了这个目的。这就是我最后要做的:

Application.php

class Application extends \Symfony\Component\Console\Application
{
    protected function configureIO(InputInterface $input, OutputInterface $output): void
    {
        $output->getFormatter()->setStyle('error', new OutputFormatterStyle('red'));
    }
}

请注意,此解决方案假定您在前端脚本中使用自己的 Application class,例如:

bin/my-command.php

$application = new \My\Application();

$application->add(new MyCommand());
// etc.

$application->run();