Symfony 2:如何覆盖另一个捆绑软件的存储库 [英] Symfony 2 : how to override repository of another bundle
问题描述
我有2个捆绑包,我想在另一个捆绑包中替换其中一个的存储库:
I have 2 bundles and i want to override the repository of one of them in the other :
我有一个源包:SourceBundle. 我有我的替代捆绑包:OverrideBundle
I have a source bundle : SourceBundle. I have my override bundle : OverrideBundle
首先,在OurVendorOverrideBundle.php中,我添加了:
First, in OurVendorOverrideBundle.php, I added :
public function getParent()
{
return 'SomeVendorSourceBundle';
}
然后
我想为SourceBundle实体的存储库添加一个自定义方法. 源实体是Response.php,其存储库是ResponseRepository.php
I wanted to add a custom method for the repository of an entity of SourceBundle. The source entity is Response.php, and its repository is ResponseRepository.php
所以我做到了:
<?php
namespace OurVendor\OverrideBundle\Repository;
use Doctrine\ORM\EntityRepository;
use SomeVendor\SourceBundle\Repository\ResponseRepository as BaseRepository;
class ResponseRepository extends BaseRepository
{
/**
*
* @return array
*/
public function getQueryExerciseAllResponsesForAllUsers($exoId)
{
$qb = $this->createQueryBuilder('r');
$qb->join('r.paper', 'p')
->join('p.exercise', 'e')
->where('e.id = ?1')
->andWhere('p.interupt = ?2')
->setParameters(array(1 => $exoId, 2 => 0));
return $qb->getQuery();
}
}
如果我未在OverrideBundle中设置实体,则会出现此错误:
If i dont set the Entity in the OverrideBundle i have this error :
The autoloader expected class "CPASimUSante\ExoverrideBundle\Entity\Response" to be defined in file "/home/www/myproject/vendor/ourvendor/override-bundle/OurVendor/OverrideBundle/Entity/Response.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
SourceBundle实体为:
The SourceBundle entity is :
<?php
namespace SomeVendor\SourceBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* SomeVendor\SourceBundle\Entity\Response
*
* @ORM\Entity(repositoryClass="SomeVendor\SourceBundle\Repository\ResponseRepository")
* @ORM\Table(name="source_response")
*/
class Response
{
...
}
因此我将实体添加到OverrideBudle中:
So i add the Entity in the OverrideBudle :
<?php
namespace OurVendor\OverrideBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use SomeVendor\SourceBundle\Entity\Response as BaseEntity;
/**
* SomeVendor\SourceBundle\Entity\Response
*
* @ORM\Entity(repositoryClass="OurVendor\OverrideBundle\Repository\ResponseRepository")
* @ORM\Table(name="override_response")
*/
class Response extends BaseEntity
{
public function __construct()
{
parent::__construct();
}
}
但是我有这个错误.
An exception occurred while executing 'SELECT u0_.id AS id0, u0_.ip AS ip1, u0_.mark AS mark2, u0_.nb_tries AS nb_tries3, u0_.response AS response4, u0_.paper_id AS paper_id5, u0_.interaction_id AS interaction_id6 FROM ujm_exoverride_response u1_ INNER JOIN ujm_paper u2_ ON u0_.paper_id = u2_.id INNER JOIN ujm_exercise u3_ ON u2_.exercise_id = u3_.id WHERE u3_.id = ? AND u2_.interupt = ?' with params ["1", 0]:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'u0_.id' in 'field list'
这似乎找不到表中的字段.所以我改为
This seems that fields in the table are not found. So i changed to
<?php
namespace OurVendor\OverrideBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use SomeVendor\SourceBundle\Entity\Response as BaseEntity;
/**
* SomeVendor\SourceBundle\Entity\Response
*
* @ORM\Entity(repositoryClass="OurVendor\OverrideBundle\Repository\ResponseRepository")
* @ORM\Table(name="source_response")
*/
class Response extends BaseEntity
{
public function __construct()
{
parent::__construct();
}
}
它奏效了.
...但是当我重新安装捆绑软件时,要测试一切是否正常,我会遇到此致命错误,指出 source_response已经定义(的确如此)
...But when i reinstalled the bundle, to test if everything was ok i had this fatal error stating that source_response is already defined (which is, indeed).
那我该怎么办?
我还读到,除非源代码扩展了MappedSuperclass,否则我无法覆盖实体,就我而言,它不会.
I have also read that i can't override an entity unless the source extends MappedSuperclass, in my case, it doesn't.
但是如果我只想覆盖它的存储库,我注定要失败?是否有可能 ?如果是的话,正确的方法是什么?
But i am doomed if i only want to override its repository ? Is it possible ? If then, what is the right way ?
如果我完全删除了替代实体的注释,则说明:
If i remove altogether the annotation for the override entity, i have :
Class "OurVendor\OverrideBundle\Entity\Response" sub class of "SomeVendor\SourceBundle\Entity\Response" is not a valid entity or mapped super class.
500 Internal Server Error - MappingException
推荐答案
可以在实体类元数据加载时覆盖其他捆绑软件中的文档映射.
Doctrine mapping in another bundles can be overriden on entity class metadata loading.
<?php
namespace Lol\RandomBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
class ClassMetadataListener
{
/**
* Run when Doctrine ORM metadata is loaded.
*
* @param LoadClassMetadataEventArgs $eventArgs
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if ('AnotherLol\AnotherRandomBundle\Entity\Response' === $classMetadata->name) {
// Do whatever you want...
$classMetadata->customRepositoryClassName = 'ThirdLol\SomeBundle\Repository\NewResponseRepository';
}
}
}
服务配置
services:
lol.random.listener.class_metadata:
class: Lol\RandomBundle\EventListener\ClassMetadataListener
tags:
- { name: doctrine.event_listener, event: loadClassMetadata }
这篇关于Symfony 2:如何覆盖另一个捆绑软件的存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!