首页 文章

如何将依赖项注入Symfony控制台命令?

提问于
浏览
30

我正在编写一个开源应用程序使用一些Symfony组件,并使用Symfony Console组件与shell进行交互 .

但是,我需要注入依赖项(在所有命令中使用),如Logger,Config对象,Yaml解析器..我通过扩展 Symfony\Component\Console\Command\Command 类解决了这个问题 . 但这使得单元测试变得更难,而且看起来不正确 .

我怎么解决这个问题?

4 回答

  • 16

    我是在为symfony2.8发言 . 您不能将构造函数添加到扩展ContainerAwareCommand的类中,因为扩展类具有 $this->getContainer() ,它使您获得服务而不是通过构造函数注入它们 .

    你可以做 $this->getContainer()->get('service-name');

  • 26

    最好不要注入容器本身,而是将容器中的服务注入到对象中 . 如果您正在使用Symfony2的容器,那么您可以执行以下操作:

    MyBundle / Resources / config / services(或者您决定放置此文件的位置):

    ...
        <services>
            <service id="mybundle.command.somecommand" class="MyBundle\Command\SomeCommand">
            <call method="setSomeService">
                 <argument type="service" id="some_service_id" />
            </call>
            </service>
        </services>
    ...
    

    然后你的命令类应如下所示:

    <?php
    namespace MyBundle\Command;
    
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputArgument;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Input\InputOption;
    use Symfony\Component\Console\Output\OutputInterface;
    use The\Class\Of\The\Service\I\Wanted\Injected;
    
    class SomeCommand extends Command
    {
       protected $someService;
       public function setSomeService(Injected $someService)
       {
           $this->someService = $someService;
       }
    ...
    

    我知道你说你没有使用依赖注入容器,但为了从@ramon实现上述答案,你必须使用它 . 至少这种方式可以对您的命令进行适当的单元测试 .

  • 12
    use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
    

    ContainerAwareCommand 扩展您的 Command 类并使用 $this->getContainer()->get('my_service_id'); 获取服务

  • 0

    自Symfony 4.2 以来,不推荐使用ContainerAwareCommand . 请改用DI .

    namespace App\Command;
    
    use Symfony\Component\Console\Command\Command;
    use Doctrine\ORM\EntityManagerInterface;
    
    final class YourCommand extends Command
    {
        /**
         * @var EntityManagerInterface
         */
        private $entityManager;
    
        public function __construct(EntityManagerInterface $entityManager)
        {
            $this->entityManager = $entityManager;
    
            parent::__construct();
        }
    
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            // YOUR CODE
            $this->entityManager->persist($object1);    
        }
    }
    

相关问题