2016-08-22 77 views
4

我是Symfony的新手。如何从控制台参数设置配置参数?

我试图通过控制台参数'format = json'来更改Monolog输出格式化程序。

总之,我想用的方式运行任何控制台命令:

app/console my_command --format=json # xml/txt/my own 

...并获得所要求的格式LoggerInterface的输出。

例如,我设置了默认格式的配置:

monolog: 
    handlers: 
     console: 
      type: console 
      channels: [!event, !doctrine] 
      formatter: json_formatter 
services: 
    json_formatter: 
     class: Monolog\Formatter\JsonFormatter 

当我创建了一些MyEventListener :: onConsoleCommand(as described here),我不能改变参数包包,因为它已经被编:“不可能在一个冻结的ParameterBag上调用set()。“

UP2:在这种情况下,我的服务的配置是这样的:

services: 
    kernel.listener.command_dispatch: 
     class: My\Listener\MyEventListener 
     autowire: true 
     tags: 
      - { name: kernel.event_listener, event: console.command } 

另一种方式,我可以在初始文件中注册控制台选项:

# app/console 
$loader = require __DIR__.'/autoload.php'; 
# ... 
$application->getDefinition()->addOption(
    new InputOption(
     'formatter', 
     'f', 
     InputOption::VALUE_OPTIONAL, 
     'The logs output formatter', 
     'json_formatter' 
    ) 
); 

但我不能找到一种方法来更改Container中的参数包。因为$ application-> getKernel() - > getContainer()仍然是空的。

那么,如何从控制台输入更改Symfony2参数?

另外,也许我可以只使用一些环境参数?但是我怎样才能在YAML配置中获得一个环境变量?

谢谢。

UP3: 我曾与环境变量实现的目标是这样的:

SYMFONY__LOG__FORMATTER=json_formatter app/console my_command 
monolog: 
    handlers: 
     console: 
      type: console 
      #... 
      formatter: '%log.formatter%' 
+0

好像'onConsoleCommand'是最便捷的方式。你可以添加更多的代码和配置尝试吗? – Ziumin

+1

我没有问题从onConsoleCommand捕获变量。这个变体的主要问题是我无法在onConsoleCommand()中调用$ container-> setParameter('formatter','json_formatter') 因为这个问题:“不可能在一个冻结的ParameterBag上调用set() “。 – kivagant

+0

我已经更新了onConsoleCommand()变体的问题并添加了服务配置。 – kivagant

回答

1

的唯一一点修改命令参数为你的应用程序处理CommandEvents::COMMAND被触发之前已经执行任何命令的每一个注册的命令。所以你可以修改它的参数并按here所述读取它们。此外,此时您已经编译了容器,并且此时无法修改服务的定义。但你可以得到任何服务。

所以我觉得你可以用以下的处理程序结束:

class LogFormatterEventListener 
{ 
    private $container; 
    private $consoleHandler; 

    public function __construct(ContainerInterface $container, HandlerInterface $consoleHandler) 
    { 
     $this->container = $container; 
     $this->consoleHandler = $consoleHandler; 
    } 

    public function onConsoleCommand(ConsoleCommandEvent $event) 
    { 
     $inputDefinition = $event->getCommand()->getApplication()->getDefinition(); 

     $inputDefinition->addOption(
      new InputOption('logformat', null, InputOption::VALUE_OPTIONAL, 'Format of your logs', null) 
     ); 

     // merge the application's input definition 
     $event->getCommand()->mergeApplicationDefinition(); 

     $input = new ArgvInput(); 

     // we use the input definition of the command 
     $input->bind($event->getCommand()->getDefinition()); 

     $formatter = $input->getOption('logformat'); 
     if ($formatter /** && $this->container->has($formatter) **/) { 
      $this->consoleHandler->setFormatter(
       $this->container->get($formatter); 
      ); 
     } 
    } 
} 
+1

我应该说这个mergeApplicationDefinition不起作用。所以,你可以运行$ event-> getCommand() - > getDefinition() - > addOption($ option); 这将强制直接选择当前命令。 第二,最好是在ContainerInterface之后向构造函数中注入ConsoleHandler $处理程序。 – kivagant

+0

谢谢。我假定文章的代码是正确的。另外我同意你的看法,我们应该避免在任何地方注入Container,但在这里执行它会变得有点棘手(我们将不得不注入所有可用格式化器的数组)。顺便说一句,这就是为什么我评论第二个检查'容器 - >有($格式化)'。 – Ziumin

+0

是的,关于格式化程序一切正常,但可以注入ConsuleHandler。 – kivagant

0

这里是另一种解决方案(与普通兼容):

配置:

monolog: 
    handlers: 
     console: 
      type: console 
      channels: [!event, !doctrine] 
      formatter: "%log.formatter%" 
services: 
    json_formatter: 
     class: Monolog\Formatter\JsonFormatter 

C ommand执行:

# colored plain text 
app/console my_command 

# json 
SYMFONY__LOG__FORMATTER=json_formatter app/console my_command