【问题标题】:How to use my Entities and Entity Managers in Symfony 2 Console Command?如何在 Symfony 2 控制台命令中使用我的实体和实体管理器?
【发布时间】:2011-11-22 16:02:55
【问题描述】:

我想对我的 Symfony2 应用程序执行一些终端命令。我已经浏览了example in the cookbook,但在这里我找不到如何访问我的设置、我的实体管理器和我的实体。在构造函数中,我使用

获取容器(这应该让我可以访问设置和实体)
$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 而不是预期的对象。我想我遗漏了一些重要的步骤,但是哪一个?我最终将如何使用我的设置和实体?

【问题讨论】:

  • 我遇到了同样的错误(我尝试在MyCommand->execute() 内部访问getContainer(),但仍然遇到同样的致命错误。我的CommandTest extends \PHPUnit_Framework_Testcase 和我通过phpunit -c app src/CompanyName/MyBundle/Tests/Commands/MyCommandTest.php any 运行它想法有什么问题?

标签: php console symfony


【解决方案1】:

我认为您不应该直接在构造函数中检索容器。相反,在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 方法。

更新:在较新版本的 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 提供评论和代码示例。

【讨论】:

  • 最新版本->getEntityManager();现在不推荐使用 ->getManager();
  • 记得扩展 ContainerAwareCommand 而不是 Command 以便访问 getContainer() 方法
  • 在 Symfony 4 中,使用 EntityManagerInterface 变量创建一个 __constructor。这个变量可以在你的其余命令中访问。这遵循自动装配/依赖注入方案。
  • 一个小补充:别忘了把use Doctrine\ORM\EntityManagerInterface;放在顶部
  • ContainerAwareCommand 自 4.2 起已弃用 - 以后有什么解决方案吗?
【解决方案2】:

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

制作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>

然后在你的 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

希望这对某人有所帮助。

【讨论】:

    【解决方案3】:

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

    class YourCmdCommand extends ContainerAwareCommand
    

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

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

    【讨论】:

    • ContainerAwareCommand 自 4.2 起已弃用 - 以后有什么解决方案吗?
    • @Isengo 显示其他最近的回复,因为我的建议太旧了
    • @Isengo 从 Symfony 4.2 开始,您可以将 Doctrine\ORM\EntityManagerInterface 注入到命令中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多