如何在Symfony

时间:2016-03-11 14:37:10

标签: php doctrine-orm doctrine symfony

我有一个独立的Symfony软件包(与Composer一起安装),包含实体和存储库,可以在连接相同数据库的应用程序之间共享。

使用配置(显示yml)将实体附加到每个应用程序:

doctrine:
    orm:
        mappings:
            acme:
                type: annotation
                dir: %kernel.root_dir%/../vendor/acme/entities/src/Entities
                prefix: Acme\Entities
                alias: Acme

嗯,这是在应用程序中包含外部实体的最简单方法,但看起来有点难看。

每当我从实体经理那里获得存储库时:

$entityManager->getRepository('Acme:User');

我获得预先配置的存储库(在实体配置中)或默认Doctrine\ORM\EntityRepository

现在我想覆盖单个实体的捆绑(或默认)存储库类。是否有机会使用某些配置/扩展/等?

我认为,最好看的方式是:

doctrine:
    orm:
         ....:
             Acme\Entities\User:
                 repositoryClass: My\Super\Repository

或者使用标签:

my.super.repository:
    class: My\Super\Repository
    tags:
        - { name: doctrine.custom.repository, entity: Acme\Entities\User }

2 个答案:

答案 0 :(得分:5)

您可以使用LoadClassMetadata事件:

class LoadClassMetadataSubscriber implements EventSubscriber
{

    /**
     * @inheritdoc
     */
    public function getSubscribedEvents()
    {
        return [
            Events::loadClassMetadata
        ];
    }

    /**
     * @param LoadClassMetadataEventArgs $eventArgs
     */
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        /**
         * @var \Doctrine\ORM\Mapping\ClassMetadata $classMetadata
         */
        $classMetadata = $eventArgs->getClassMetadata();

        if ($classMetadata->getName() !== 'Acme\Entities\User') {
            return;
        }

        $classMetadata->customRepositoryClassName = 'My\Super\Repository';
    }

}

Doctrine Events

  

使用配置(显示yml)将实体附加到每个应用程序:   嗯,这是在应用程序中包含外部实体的最简单方法,但看起来有点难看。

您可以启用auto_mapping

答案 1 :(得分:3)

适用于Doctrine版本< 2.5

除了Artur Vesker的回答,我还找到了另一种方式:覆盖全球repository_factory

config.yml:

doctrine:
    orm:
        repository_factory: new.doctrine.repository_factory

services.yml:

new.doctrine.repository_factory:
    class: My\Super\RepositoryFactory

存储库工厂:

namespace My\Super;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\DefaultRepositoryFactory;

class RepositoryFactory extends DefaultRepositoryFactory
{
    /**
     * @inheritdoc
     */
    protected function createRepository(EntityManagerInterface $entityManager, $entityName)
    {
        if ($entityName === Acme\Entities\User::class) {
            $metadata = $entityManager->getClassMetadata($entityName);
            return new ApplicationRepository($entityManager, $metadata);
        }

        return parent::createRepository($entityManager, $entityName);
    }
}

毫无疑问,实施LoadClassMetadataSubscriber是一种更好的方法。