将依赖注入实体库 [英] Injecting dependency into entity repository

查看:109
本文介绍了将依赖注入实体库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我尝试过听过 loadClassMetadata 事件并在存储库中使用setter注入,但这自然导致无限循环,因为在触发相同事件的事件中调用 getRepository



查看 Doctrine\ORM\EntityManager :: getRepository 方法后,似乎存储库根本没有使用依赖注入,而是在功能级别实例化:

  public function getRepository($ entityName)
{
$ entityName = ltrim($ entityName,'\\\'');
if(isset($ this-> repositories [$ entityName])){
return $ this-> repositories [$ entityName];
}

$ metadata = $ this-> getClassMetadata($ entityName);
$ customRepositoryClassName = $ metadata-> customRepositoryClassName;

if($ customRepositoryClassName!== null){
$ repository = new $ customRepositoryClassName($ this,$ metadata);
} else {
$ repository = new EntityRepository($ this,$ metadata);
}

$ this-> repositories [$ entityName] = $ repository;

return $ repository;
}

任何想法?

解决方案

如果您使用自定义EntityManager,您可以覆盖 getRepository 方法。因为这不涉及 loadClassMetadata 事件,所以你不会遇到无限循环。



你会首先必须将依赖关系传递给您的自定义EntityManager,然后使用setter注入将其传递给存储库对象。



我回答了如何使用自定义EntityManager < a href =https://stackoverflow.com/questions/8138962/is-there-a-way-to-specify-doctrine2-entitymanager-implementation-class-in-symfon/8140007#8140007>这里 ,但我会复制以下答案:



1 - 覆盖 doctrine.orm.entity_manager.class 参数指向您的自定义实体管理器(应扩展 Doctrine\ORM\EntityManager 。)



2 - 您的自定义实体管理器必须覆盖 create 方法,以便它返回一个类的实例。请参阅下面的示例,并注意关于 MyEntityManager 的最后一行:

  public static function create($ conn,Configuration $ config,EventManager $ eventManager = null){
if(!$ config-> getMetadataDriverImpl()){
throw ORMException :: missingMappingDriverImpl();
}

if(is_array($ conn)){
$ conn = \Doctrine\DBAL\DriverManager :: getConnection($ conn,$ config,($ eventManager?:new EventManager()));
} else if($ conn instanceof Connection){
if($ eventManager!== null&& $ conn-> getEventManager()!== $ eventManager){
throw ORMException :: mismatchedEventManager();
}
} else {
throw new \InvalidArgumentException(Invalid argument:。$ conn);
}

//这是您返回自定义类的实例的地方!
返回新的MyEntityManager($ conn,$ config,$ conn-> getEventManager());
}

您还需要使用你课上的以下内容:

 使用Doctrine\ORM\EntityManager; 
使用Doctrine\ORM\Configuration;
使用Doctrine\ORM\ORMException;
使用Doctrine\Common\EventManager;
使用Doctrine\DBAL\Connection;

修改



由于默认实体管理器是从创建方法创建的,因此您不能简单地将服务注入到该方法中。但是,由于您正在创建一个自定义实体管理器,您可以将其连接到服务容器并注入所需的任何依赖项。



然后从覆盖的 getRepository 方法中,您可以执行像

$ repository-> setFoo($这 - >富)。这是一个非常简单的例子 - 在调用之前,您可能需要首先检查 $ repository 是否具有 setFoo 方法。实现取决于您,但这显示了如何使用setter注入进行存储库。


Is there a simple way to inject a dependency into every repository instance in Doctrine2 ?

I have tried listening to the loadClassMetadata event and using setter injection on the repository but this naturally resulted in a infinite loop as calling getRepository in the event triggered the same event.

After taking a look at the Doctrine\ORM\EntityManager::getRepository method it seems like repositories are not using dependency injection at all, instead they are instantiated at the function level:

public function getRepository($entityName)
{
    $entityName = ltrim($entityName, '\\');
    if (isset($this->repositories[$entityName])) {
        return $this->repositories[$entityName];
    }

    $metadata = $this->getClassMetadata($entityName);
    $customRepositoryClassName = $metadata->customRepositoryClassName;

    if ($customRepositoryClassName !== null) {
        $repository = new $customRepositoryClassName($this, $metadata);
    } else {
        $repository = new EntityRepository($this, $metadata);
    }

    $this->repositories[$entityName] = $repository;

    return $repository;
}

Any ideas ?

解决方案

If you use a custom EntityManager you could override the getRepository method. Since this doesn't involve the loadClassMetadata event, you won't run into an infinite loop.

You would first have to pass the dependency to your custom EntityManager, and then you'd pass it to the repository object using setter injection.

I answered how to use a custom EntityManager here, but I'll replicate the answer below:

1 - Override the doctrine.orm.entity_manager.class parameter to point to your custom entity manager (which should extend Doctrine\ORM\EntityManager.)

2 - Your custom entity manager must override the create method so that it returns an instance of your class. See my example below, and note the last line regarding MyEntityManager:

public static function create($conn, Configuration $config, EventManager $eventManager = null) {
        if (!$config->getMetadataDriverImpl()) {
            throw ORMException::missingMappingDriverImpl();
        }

        if (is_array($conn)) {
            $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ? : new EventManager()));
        } else if ($conn instanceof Connection) {
            if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
                throw ORMException::mismatchedEventManager();
            }
        } else {
            throw new \InvalidArgumentException("Invalid argument: " . $conn);
        }

        // This is where you return an instance of your custom class!
        return new MyEntityManager($conn, $config, $conn->getEventManager());
    }

You'll also need to use the following in your class:

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;

Edit

Since the default entity manager is created from the create method, you can't simply inject a service into it. But since you're making a custom entity manager, you can wire it up to the service container and inject whatever dependencies you need.

Then from within the overridden getRepository method you could do something like
$repository->setFoo($this->foo). That's a very simple example - you may want to first check if $repository has a setFoo method before calling it. The implementation is up to you, but this shows how to use setter injection for a repository.

这篇关于将依赖注入实体库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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