依赖注射与定制的原则2水化器 [英] Dependency injection with custom Doctrine 2 hydrator

查看:133
本文介绍了依赖注射与定制的原则2水化器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Symfony 2项目中在Doctrine 2中建立了一个定制的hydrator,但是为了完成它需要的工作,它需要另一个服务。 自定义水化器的文档只显示了如何提供一个hydrator类,所以没有办法注入依赖关系。



例如:

  $ em-> getConfiguration() - > addCustomHydrationMode('CustomHydrator','MyProject\Hydrators\CustomHydrator'); 

我怀疑主义正在初始化hydrators本身,因此任何依赖将需要通过其他是否有办法提供一个自定义的水化工厂或类似于Doctrine,这将允许注入附加的依赖关系?






答案:感谢Denis V p>

我的工作如下。我不能发布实际的代码,所以我把一些虚拟占位符放在一起,所以你可以看到它如何配合在一起。



src / Acme / ExampleBundle / resources / config / services.yml

 服务:
doctrine.orm.entity_manager.abstract:
类:Acme\ExampleBundle\Entity\DoctrineEntityManager
factory_class:Acme\ExampleBundle\Entity\DoctrineEntityManager
factory_method:create
abstract:true
call :
- [setMyDependency,[@ acme.my_custom_service]]

src / Acme / ExampleBundle / Entity / DoctrineEntityManager.php

 命名空间Acme\ExampleBundle\Entity; 

使用Acme\ExampleBundle\Hydrator\MyHydrator;
使用Doctrine\Common\EventManager;
使用Doctrine\DBAL\Connection;
使用Doctrine\ORM\Configuration;
使用Doctrine\ORM\EntityManager作为BaseEntityManager;
使用Doctrine\ORM\ORMException;
使用Doctrine\ORM\Query;

class DoctrineEntityManager extends BaseEntityManager
{
protected $ myDependency;

/ **
*注意:这必须重新定义为Doctrine自己的实体管理器有自己的类名称硬编码在
* /
public static function create $ conn,Configuration $ config,EventManager $ eventManager = null)
{
if(!$ config-> getMetadataDriverImpl()){
throw ORMException :: missingMappingDriverImpl();
}

switch(true){
case(is_array($ conn)):
$ conn = \Doctrine\DBAL\DriverManager :: getConnection (
$ conn,$ config,($ eventManager?:new EventManager())
);
break;

case($ conn instanceof Connection):
if($ eventManager!== null&& $ conn-> getEventManager()!== $ eventManager){
抛出ORMException :: mismatchatchedEventManager();
}
break;

默认值:
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'){
返回新的MyHydrator($ this ,$ this-> myDependency);
}

return parent :: newHydrator($ hydrationMode);
}
}

src / Acme / ExampleBundle / Hydrator / MyHydrator.php

 命名空间Acme\ExampleBundle\Hydrator; 

请使用Doctrine\ORM\EntityManager;
使用Doctrine\ORM\Internal\Hydration\ObjectHydrator;

class MyHydrator extends ObjectHydrator
{
protected $ myDependency;

public __construct(EntityManager $ em,$ myDependency)
{
parent :: __ construct($ em);

$ this-> myDependency = $ myDependency;
}

保护函数hydrateAllData()
{
/ *水合物与我的依赖关系* /
}
}


解决方案

尝试将其添加到config.yml

  doctrine:
orm:
hydrators:
CustomHydrator:MyProject\Hydrators\CustomHydrator

更新



注入任何东西到Hydrator本身,你可以创建一个自定义的EntityManager(你建议自己)。



可以这样做:

 服务:
name_of_your_custom_manager:
类:%doctrine.orm.entity_manager.class%
factory_service:doctrine
factory_method:getManager
arguments:[name_of_your_custom_manager]
调用:
- [setCustomDependency,[@acme_bun dle.custom_dependency]]


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.

For example:

$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator');

I suspect Doctrine is initialising the hydrators itself and as such any dependencies would need to be passed through some other Doctrine classes first.

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.


Answer: Thanks to 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:          Acme\ExampleBundle\Entity\DoctrineEntityManager
        factory_class:  Acme\ExampleBundle\Entity\DoctrineEntityManager
        factory_method: create
        abstract:       true
        calls:
            - [ setMyDependency, [@acme.my_custom_service]]

src/Acme/ExampleBundle/Entity/DoctrineEntityManager.php

namespace Acme\ExampleBundle\Entity;

use Acme\ExampleBundle\Hydrator\MyHydrator;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager as BaseEntityManager;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\Query;

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 = \Doctrine\DBAL\DriverManager::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 Acme\ExampleBundle\Hydrator;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Internal\Hydration\ObjectHydrator;

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 */
    }
}

解决方案

Try adding this in your config.yml

doctrine:
    orm:
        hydrators:
            CustomHydrator: MyProject\Hydrators\CustomHydrator

UPDATE

As you cannot inject anything to the Hydrator itself, you can instead create a custom EntityManager (that you suggested yourself).

It can be done this way:

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"] ]

这篇关于依赖注射与定制的原则2水化器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆