php 如何在 Symfony 2 控制台命令中使用我的实体和实体管理器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7512425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:50:30  来源:igfitidea点击:

How to use my Entities and Entity Managers in Symfony 2 Console Command?

phpconsolesymfony

提问by Fester Bestertester

I want to a few terminal commands to my Symfony2 application. I've gone through the example in the cookbook, but I couldn't find out how to access my settings, my entity manager and my entities here. In the constructor, I get the container (which should yield me access to settings and entities) using

我想对我的 Symfony2 应用程序执行一些终端命令。我已经浏览了说明书中示例,但我无法找到如何在此处访问我的设置、实体管理器和实体。在构造函数中,我使用

$this->container = $this->getContainer();

But this call generates an error:

但是这个调用会产生一个错误:

Fatal error: Call to a member function getKernel() on a non-object in /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php on line 38

致命错误:在第 38 行的 /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php 中的非对象上调用成员函数 getKernel()

Basically, in ContainerAwareCommand->getContainer() the call to

基本上,在 ContainerAwareCommand->getContainer() 中调用

$this->getApplication()

returns NULL and not an object as expected. I guess that I left some important step out, but which one? And how will I finally be able to use my settings and entities?

返回 NULL 而不是预期的对象。我想我遗漏了一些重要的步骤,但哪一步呢?我将如何最终能够使用我的设置和实体?

回答by Matt

I think you should not retrieve the container in the constructor directly. Instead, retrieve it in the configuremethod or in the executemethod. In my case, I get my entity manager just at the start of the executemethod like this and everything is working fine (tested with Symfony 2.1).

我认为您不应该直接在构造函数中检索容器。相反,在configure方法或execute方法中检索它。就我而言,我在execute方法开始时就得到了我的实体管理器,并且一切正常(使用 Symfony 2.1 测试)。

protected function execute(InputInterface $input, OutputInterface $output)
{
    $entityManager = $this->getContainer()->get('doctrine')->getEntityManager();

    // Code here
}

I think that the instantiation of the application object is not done yet when you are calling getContainerin your constructor which result in this error. The error comes from the getContainermethod tyring to do:

我认为当您getContainer在构造函数中调用导致此错误时,应用程序对象的实例化尚未完成。错误来自于getContainer要执行的方法:

$this->container = $this->getApplication()->getKernel()->getContainer();

Since getApplicationis not an object yet, you get the a error saying or are calling a method getKernelon a non-object.

由于getApplication还不是对象,您会收到一条错误消息,说明或正在调用getKernel非对象上的方法。

Update: In newer version of Symfony, getEntityManagerhas been deprecated (and could have been removed altogether by now). Use $entityManager = $this->getContainer()->get('doctrine')->getManager();instead. Thanks to Chausserfor pointing it.

更新:在较新版本的 Symfony 中,getEntityManager已被弃用(现在可能已被完全删除)。使用$entityManager = $this->getContainer()->get('doctrine')->getManager();来代替。感谢Chausser指出它。

Update 2: In Symfony 4, auto-wiring can be used to reduce amount of code needed.

更新 2:在 Symfony 4 中,可以使用自动装配来减少所需的代码量。

Create a __constructorwith a EntityManagerInterfacevariable. This variable will be accessible in the rest of your commands. This follows the auto-wiring Dependency Injection scheme.

创建__constructor一个EntityManagerInterface变量。此变量将可在您的其余命令中访问。这遵循自动布线依赖注入方案。

class UserCommand extends ContainerAwareCommand { 
  private $em; 

  public function __construct(?string $name = null, EntityManagerInterface $em) { 
    parent::__construct($name); 

    $this->em = $em;
  } 

  protected function configure() { 
    **name, desc, help code here** 
  }

  protected function execute(InputInterface $input, OutputInterface $output) { 
    $this->em->getRepository('App:Table')->findAll();
  }
}

Credits to @profm2 for providing the comment and the code sample.

感谢@profm2 提供评论和代码示例。

回答by stloc

extends your command class from ContainerAwareCommand instead of Command

从 ContainerAwareCommand 而不是 Command 扩展你的命令类

class YourCmdCommand extends ContainerAwareCommand

and get entity manager like this :

并像这样获得实体管理器:

$em = $this->getContainer()->get('doctrine.orm.entity_manager');

回答by TheLastTamurai

I know that Matt's answer solved the question, But if you've more than one entity manager, you can use this:

我知道马特的回答解决了这个问题,但如果你有多个实体管理器,你可以使用这个:

Make model.xml with:

使用以下命令制作 model.xml:

<?xml version="1.0" encoding="UTF-8" ?>

<container xmlns="http://symfony.com/schema/dic/services"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://symfony.com/schema/dic/services         http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
    <service id="EM_NAME.entity_manager" alias="doctrine.orm.entity_manager" />
</services>
</container>

Then load this file in your DI extension

然后在你的 DI 扩展中加载这个文件

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('model.xml');

Then you can use it anywhere. In Console Command execute:

然后你可以在任何地方使用它。在控制台命令中执行:

$em = $this->getContainer()->get('EM_NAME.entity_manager');

and don't forget at end to :

最后不要忘记:

$em->flush();

You can now use it as a argument in another service in services.yml:

您现在可以将它用作 services.yml 中另一个服务的参数:

services:
    SOME_SERVICE:
        class: %parameter.class%
        arguments:
            - @EM_NAME.entity_manager

Hope this help someone.

希望这有助于某人。