我正在尝试在控制器之外获取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
答案 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');