2016-08-22 75 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