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

发布于 2024-12-05 15:40:10 字数 642 浏览 1 评论 0原文

我想要对我的 Symfony2 应用程序执行一些终端命令。我已经浏览了食谱中的示例,但我不知道如何访问我的设置,我的实体管理器和我的实体在这里。在构造函数中,我使用以下方法获取容器(这应该让我能够访问设置和实体)

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

但是此调用会生成错误:

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

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

$this->getApplication()

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

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

$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

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

$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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

远山浅 2024-12-12 15:40:10

我认为你不应该直接在构造函数中检索容器。相反,请在 configure 方法或 execute 方法中检索它。就我而言,我在 execute 方法的开头就得到了我的实体管理器,就像这样,一切都工作正常(使用 Symfony 2.1 进行了测试)。

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

    // Code here
}

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

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

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

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

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

使用 EntityManagerInterface 变量创建一个 __constructor 。该变量将可以在其余命令中访问。这遵循自动装配依赖注入方案。

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();
  }
}

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

I think you should not retrieve the container in the constructor directly. Instead, retrieve it in the configure method or in the execute method. In my case, I get my entity manager just at the start of the execute method like this and everything is working fine (tested with 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 getContainer in your constructor which result in this error. The error comes from the getContainer method tyring to do:

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

Since getApplication is not an object yet, you get the a error saying or are calling a method getKernel on a non-object.

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

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

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

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.

鹊巢 2024-12-12 15:40:10

从 ContainerAwareCommand 而不是 Command 扩展命令类

class YourCmdCommand extends ContainerAwareCommand

并获取实体管理器,如下所示:

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

extends your command class from ContainerAwareCommand instead of Command

class YourCmdCommand extends ContainerAwareCommand

and get entity manager like this :

$em = $this->getContainer()->get('doctrine.orm.entity_manager');
可遇━不可求 2024-12-12 15:40:10

我知道 Matt 的回答解决了这个问题,但是如果您有多个实体管理器,您可以使用以下命令:

Make model.xml with:

<?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>

然后将此文件加载到您的 DI 扩展中

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

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

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

并且不要忘记最后:

$em->flush();

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

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

希望这对某人有帮助。

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:

<?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

$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:
    SOME_SERVICE:
        class: %parameter.class%
        arguments:
            - @EM_NAME.entity_manager

Hope this help someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文