Symfony2 getdoctrine在Model / Controller之外

时间:2013-11-08 09:12:01

标签: symfony doctrine

我正在尝试在控制器之外获取Doctrine()。 我创建了这项服务:

配置/ services.yml

services:
  update_command:
    class: project\projBundle\Command\Update
    arguments: ['@doctrine.orm.entity_manager']

并在我的app / config / config.yml

imports:
    - { resource: "@projectprojBundle/Resources/config/services.yml" }

以及我想要使用的类:

namespace project\projBundle\Command;
use Doctrine\ORM\EntityManager;

class Update {
    protected $em;
    public function __construct(EntityManager $em) {
        $this->em = $em;
    }

但每次我想这样做:(我这样做了吗?

$up = new Update();

我收到了这个错误:

Catchable Fatal Error: Argument 1 passed to ...\Update::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in .../Update.php line 7  

3 个答案:

答案 0 :(得分:7)

简单解决方案

如果您正在实施Symfony命令(可以在cron选项卡中执行),则可以从命令访问服务容器。

<?php
namespace MyProject\MyBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Doctrine\ORM\EntityManager;

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

class UpdateCommand extends ContainerAwareCommand
{
    protected $em;

    protected function configure()
    {
        $this->setName('myproject:mybundle:update') ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->em = $this->getContainer()->get('doctrine.orm.entity_manager');
    }
}

这样,您从命令中获取实体管理器,而不需要将此类声明为服务。因此,您可以删除services.yml文件中添加的配置。

另一种解决方案(清洁工)

此解决方案可以更好地分离关注点,因此可以轻松地在Symfony应用程序的其他部分进行单元测试和重用(不仅仅是作为命令)。

将“update”命令的所有逻辑部分移动到您将声明为服务的专用类:

<?php
namespace MyProject\MyBundle\Service;

use Doctrine\ORM\EntityManager;

class MyUpdater
{
    protected $em;

    public function __construct($em)
    {
        $this->em = $em;
    }

    public function runUpdate()
    {
        // All your logic code here
    }
}

将其声明为services.yml文件中的服务:

services:
    myproject.mybundle.myupdater:
        class: MyProject\MyBundle\Service\MyUpdater
        arguments: ['@doctrine.orm.entity_manager']

只需通过命令调用您的服务:

<?php
namespace MyProject\MyBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

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

class UpdateCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this->setName('myproject:mybundle:update') ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $myUpdater = $this->getContainer()->get('myproject.mybundle.myupdater');
        $myUpdater->runUpdate();
    }
}

答案 1 :(得分:2)

您必须注入新创建的@update_command服务或从容器中获取服务,以便自动注入@doctrine.orm.entity_manager服务。

您只是创建没有参数的对象,而不是服务。 Update期望检索实体管理器实例,但您不提供它。

$up = new Update();

在像控制器一样的ContainerAware类中,您可以获得这样的服务:

 $up = $this->container->get('update_command');

否则,将要使用update_command的类转换为服务,并像处理服务本身中的实体管理器一样注入@update_command

答案 2 :(得分:0)

删除app / config / config.yml中的以下代码,您的services.yml将自动加载......

imports:
    - { resource: "@projectprojBundle/Resources/config/services.yml" }

在一个Action新实例中你可以做到:

  $up = $this->get('update_command');