【问题标题】:how to get configuration parameter into a command如何将配置参数放入命令中
【发布时间】:2020-07-31 12:55:21
【问题描述】:

我正在尝试将配置参数放入命令中。

我在parameters 键下的app/config/config.yml 中添加了参数。

我可以在控制器中使用$this->getParameter("PRAMETER_NAME") 来手动执行一些操作。

我正在编写一个命令来自动使用 CRON 作业执行相同的操作。

我找不到如何获取命令中的参数。

【问题讨论】:

  • @fyrye 我正在使用 Symfony 3.4。

标签: php symfony symfony-3.4


【解决方案1】:

您可以将容器注入到声明它ContainerAware 的命令中(更糟糕),您可以将ParamterBag 作为服务注入(更好),或者您可以在命令构造函数中注入参数(最好)。

在您的命令中,您必须接受构造函数中的参数。例如:

你的命令.php:

<?php

class YourCommand extends Command {
  public function __construct(string $parameter) {
    parent::__construct('app:my-command');
    $this->parameter = $parameter;
  }
}

services.yaml

services:
  YourCommand:
    arguments:
      - '%parameter_name%'

【讨论】:

  • 我做了第三种方法,完美!
  • 请不要忘记parent::__construct();,以确保调用Command::configure()并声明InputDefinition
  • 我忘记了,Symfony 告诉我 ^^
【解决方案2】:

参数绑定

在 Symfony 3.4 或更高版本中,recommended approach 将使用 AutowiringArgument Binding。允许将变量名称的声明“绑定”为配置文件中定义的所有服务的参数,而无需显式指定使用该参数的每个服务。

在定义命令服务和自动装配的同一配置文件中,将bind 选项添加到_defaults 规范,以及所需的参数变量名称。

app/config/services.yml

parameters:
    PARAMETER_NAME: 'test'

services:
    _defaults:
        bind:
            $PARAMETER_NAME: '%PARAMETER_NAME%'
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    AppBundle\:
        resource: '../../src/AppBundle/*'
        exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'

    # Additional Services Below Here

之后,Symfony 会在将参数值指定为服务构造函数的参数时,自动将参数值传递给绑定的变量名。

src/AppBundle/Command/MyCommand.php

namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends Command
{

    private $PARAMETER_NAME;

    public function __construct($PARAMETER_NAME)
    {
        $this->PARAMETER_NAME = $PARAMETER_NAME;
        parent::__construct();
    }

    // ...

    public function execute(InputInterface $input, OutputInterface $output)
    {
        dump($this->PARAMETER_NAME);
        exit;
    }

    public static function getDefaultName()
    {
        return 'app:my_command';
    }
}

参数注入

另一种避免需要覆盖__construct 的方法是使用方法注入参数值,即使用calls 扩展服务定义。

app/config/services.yml

parameters:
    PARAMETER_NAME: 'test'

services:
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    AppBundle\:
        resource: '../../src/AppBundle/*'
        exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'

    AppBundle\Command\MyCommand:
        calls:
            - [setParameterName, ['%PARAMETER_NAME%']]

    # Additional Services Below Here

src/AppBundle/Command/MyCommand.php

namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends Command
{

    private $parameterName;

    // ...

    public function execute(InputInterface $input, OutputInterface $output)
    {
        dump($this->parameterName);
        exit;
    }

    public function setParameterName($value)
    {
        $this->parameterName = $value;
    }
}

或者,可以使用依赖注入将 Container 或 ParameterBag 注入到命令中,使其功能类似于控制器。

注入整个 Container 或 ParameterBag 是highly discouraged只注入需要的参数和服务 改为。

在以下任一示例中,确保启用autowireautoconfigure

app/config/services.yml

parameters:
    PARAMETER_NAME: 'test'

services:
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    AppBundle\:
        resource: '../../src/AppBundle/*'
        exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'

    # Additional Services Below Here

ContainerAwareCommand

(从 Symfony 4.2 开始贬值 - 在 Syfmony 5.0+ 中删除)

使用ContainerAwareCommand 与参数注入类似,但不是调用setParameterName()。启用autowiringautoconfig 后,Symfony 将使用从ContainerAwareInterface 实现的setContainer() 自动注入整个容器。

src/AppBundle/Command/MyCommand.php

namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends ContainerAwareCommand
{

    // ...

    public function execute(InputInterface $input, OutputInterface $output)
    {
        dump($this->getContainer()->getParameter('PARAMETER_NAME'));
        exit;
    }
}

参数包注入

需要 Symfony 4.1+

要在启用autowire 时使用依赖注入注入ParameterBag,请将ParameterBagInterface 添加到服务构造函数中。

src/AppBundle/Command/MyCommand.php

namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MyCommand extends Command
{

    private $parameterBag;

    public function __construct(ParameterBagInterface $parameterBag)
    {
         $this->parameterBag = $parameterBag;
         parent::__construct();
    }

    // ...

    public function execute(InputInterface $input, OutputInterface $output)
    {
        dump($this->parameterBag->get('PARAMETER_NAME'));
        exit;
    }

    public static function getDefaultName()
    {
        return 'app:my_command';
    }
}

【讨论】:

    猜你喜欢
    • 2021-06-15
    • 2014-11-27
    • 2014-03-26
    • 2012-10-21
    • 2018-03-30
    • 2016-04-21
    • 1970-01-01
    • 2023-02-18
    • 2011-12-19
    相关资源
    最近更新 更多