问题描述
我正在 Symfony 2 项目中的 Doctrine 2 中设置自定义水合器,但要让它执行所需的操作,需要其他服务.自定义水化器的文档 只展示了如何提供 hydrator 类,因此无法注入依赖项.
I'm setting up a custom hydrator in Doctrine 2 in a Symfony 2 project, but for it to do what it needs it requires another service. The documentation for custom hydrators only shows how to provide a hydrator class, so there's no way to inject dependencies.
例如:
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProjectHydratorsCustomHydrator');
我怀疑 Doctrine 正在初始化 hydrator 本身,因此任何依赖项都需要首先通过其他一些 Doctrine 类.
I suspect Doctrine is initialising the hydrators itself and as such any dependencies would need to be passed through some other Doctrine classes first.
有没有办法提供一个自定义的水化工厂"或类似于 Doctrine 的东西来允许注入额外的依赖项?如果没有此功能,定制水化器似乎相当有限.
Is there a way to provide a custom "hydration factory" or similar to Doctrine that would allow injection of additional dependencies? Custom hydrators seem fairly limited without this capability.
答案:感谢 Denis V
我按如下方式工作.我无法发布实际代码,因此我将一些虚拟占位符放在一起,以便您了解它们是如何组合在一起的.
I got this working as follows. I can't post the actual code so I've put together some dummy placeholders so you can see how it fits together.
src/Acme/ExampleBundle/resources/config/services.yml
services:
doctrine.orm.entity_manager.abstract:
class: AcmeExampleBundleEntityDoctrineEntityManager
factory_class: AcmeExampleBundleEntityDoctrineEntityManager
factory_method: create
abstract: true
calls:
- [ setMyDependency, [@acme.my_custom_service]]
src/Acme/ExampleBundle/Entity/DoctrineEntityManager.php
namespace AcmeExampleBundleEntity;
use AcmeExampleBundleHydratorMyHydrator;
use DoctrineCommonEventManager;
use DoctrineDBALConnection;
use DoctrineORMConfiguration;
use DoctrineORMEntityManager as BaseEntityManager;
use DoctrineORMORMException;
use DoctrineORMQuery;
class DoctrineEntityManager extends BaseEntityManager
{
protected $myDependency;
/**
* Note: This must be redefined as Doctrine's own entity manager has its own class name hardcoded in.
*/
public static function create($conn, Configuration $config, EventManager $eventManager = null)
{
if (!$config->getMetadataDriverImpl()) {
throw ORMException::missingMappingDriverImpl();
}
switch (true) {
case (is_array($conn)):
$conn = DoctrineDBALDriverManager::getConnection(
$conn, $config, ($eventManager ?: new EventManager())
);
break;
case ($conn instanceof Connection):
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
throw ORMException::mismatchedEventManager();
}
break;
default:
throw new InvalidArgumentException("Invalid argument: " . $conn);
}
return new self($conn, $config, $conn->getEventManager());
}
public function setMyDependency($myCustomService)
{
$this->myDependency = $myCustomService;
}
public function newHydrator($hydrationMode)
{
if ($hydrationMode == 'MyHydrationMode') {
return new MyHydrator($this, $this->myDependency);
}
return parent::newHydrator($hydrationMode);
}
}
src/Acme/ExampleBundle/Hydrator/MyHydrator.php
namespace AcmeExampleBundleHydrator;
use DoctrineORMEntityManager;
use DoctrineORMInternalHydrationObjectHydrator;
class MyHydrator extends ObjectHydrator
{
protected $myDependency;
public __construct(EntityManager $em, $myDependency)
{
parent::__construct($em);
$this->myDependency = $myDependency;
}
protected function hydrateAllData()
{
/* hydration stuff with my dependency here */
}
}
推荐答案
尝试在 config.yml 中添加这个
Try adding this in your config.yml
doctrine:
orm:
hydrators:
CustomHydrator: MyProjectHydratorsCustomHydrator
更新
由于您无法向 Hydrator 本身注入任何内容,您可以改为创建自定义 EntityManager(您自己建议).
As you cannot inject anything to the Hydrator itself, you can instead create a custom EntityManager (that you suggested yourself).
可以这样做:
services:
name_of_your_custom_manager:
class: %doctrine.orm.entity_manager.class%
factory_service: doctrine
factory_method: getManager
arguments: ["name_of_your_custom_manager"]
calls:
- [ setCustomDependency, ["@acme_bundle.custom_dependency"] ]
这篇关于使用自定义 Doctrine 2 hydrator 进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!