[英]Doctrine 2 Index Inheritance
i am new to Doctrine 2 am i trying to figure out how to do index inheritance with it.我是 Doctrine 2 的新手,我想弄清楚如何用它进行索引继承。
What i am trying to achieve is to have a base class that defines some default columns along with necessary indexes for all entities within the application.我想要实现的是有一个基类,它定义了一些默认列以及应用程序中所有实体的必要索引。
Example: All tables in my application will have created_on
and modified_on
, so i prepared one base @MappedSuperclass
with those 2 columns in it.示例:我的应用程序中的所有表都将具有
created_on
和modified_on
,因此我准备了一个包含这两列的基础@MappedSuperclass
。
Here is my code:这是我的代码:
<?php
/**
* @MappedSuperclass
*/
abstract class EntityAbstract
{
/**
* @Column(type="datetime", name="created_on", nullable=false)
*/
protected $createdOn;
/**
* @Column(type="datetime", name="modified_on", nullable=true)
*/
protected $modifiedOn;
}
/**
* @Entity
* @Table(name="member", indexes={@Index(name="credential", columns={"email_address", "password"})})
*/
class Member extends EntityAbstract
{
/**
* @Column(type="string", name="full_name", length=50)
*/
protected $fullName;
/**
* @Column(type="string", name="email_address", length=50, unique=true, nullable=false)
*/
protected $emailAddress;
/**
* @Column(type="string", name="password", length=40, nullable=false)
*/
protected $password;
}
?>
I want to enforce created_on
to be an index, so i put @Index
annotation in the base class for this particular column.我想强制
created_on
成为一个索引,所以我在这个特定列的基类中放置了@Index
注释。 Hoping that this will result in 2 indexes for Member
which is created_on
and email_address
+ password
combination.希望这将为
Member
产生 2 个索引,即created_on
和email_address
+ password
组合。 This however results in indexes of the base class being overriden by the child class, thus created_on
is not an index.然而,这会导致子类覆盖基类的索引,因此
created_on
不是索引。
/**
* @MappedSuperclass
* @Table(indexes={@Index(name="timestampcreated", columns={"created_on"})})
*/
abstract class EntityAbstract
How do i achieve this in Doctrine 2?我如何在 Doctrine 2 中实现这一点? Have looked at single table inheritance, but my understanding is that it's meant for different purpose.
看过单表继承,但我的理解是它用于不同的目的。
Here's a full solution for the way laid out at https://github.com/doctrine/orm/issues/5928#issuecomment-273624392 , thanks to https://medium.com/@alexkunin/doctrine-symfony-adding-indexes-to-fields-defined-in-traits-a8e480af66b2这是https://github.com/doctrine/orm/issues/5928#issuecomment-273624392的完整解决方案,感谢https://medium.com/@alexkunin/doctrine-symfony-adding-indexes -to-fields-defined-in-traits-a8e480af66b2
namespace App\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use App\Entity\Member;
class MemberIndexListener
{
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
/** @var Doctrine\ORM\Mapping\ClassMetadata $classMetadata */
$classMetadata = $eventArgs->getClassMetadata();
if (Member::class === $classMetadata->getName())
{
$prefix = strtolower((new \ReflectionClass($classMetadata->getName()))->getShortName()); // you can omit this line and ...
$classMetadata->table['indexes'][$prefix.'_created_on'] = // ... replace `[$prefix.'_created_on']` with `[]` for automatic index naming
['columns' => ['username']
];
// For UniqueConstraints, use:
// $classMetadata->table['uniqueConstraints'][...] = ...
}
}
}
And in services.yaml
:在
services.yaml
:
services:
App\EventListener\MemberIndexListener:
tags:
- { name: doctrine.event_listener, event: loadClassMetadata }
I wanted to do the same thing, but @Table
is not allowed in @mappedSuperclass
classes.我想做同样的事情,但是
@mappedSuperclass
类中不允许使用@Table
。 I've posted issue on doctrine2 github page https://github.com/doctrine/doctrine2/issues/5928 and the answer is:我在doctrine2 github页面https://github.com/doctrine/doctrine2/issues/5928上发布了问题,答案是:
@Table is not valid on a mappedsuperclass.
@Table 在映射超类上无效。
When you think about it is sounds logical, but still, it would be nice if there is such functionality, to inherit indexes and other declarations.当您考虑它时听起来很合乎逻辑,但是,如果有这样的功能,继承索引和其他声明,那就太好了。
This is my solution for automatic index inheritance.这是我的自动索引继承解决方案。
You can specify indexes in table annotation of mapped superclass.您可以在映射超类的表注释中指定索引。 And all children will extend them.
所有的孩子都会扩展它们。
The listener takes indexes of all parent mapped superclases.侦听器获取所有父映射超类的索引。
#src/EventListener/InheritIndexListener.php
<?php
namespace App\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadata;
final class InheritIndexListener
{
/** @var EntityManagerInterface */
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
$name = $classMetadata->name;
if (!$classMetadata->isMappedSuperclass) {
foreach (class_parents($name) as $parent) {
$this->addParentIndexes($parent, $classMetadata);
}
}
}
private function addParentIndexes(string $parent, ClassMetadata $classMetadata): void
{
$parentMetadata = $this->entityManager
->getClassMetadata($parent);
foreach ($parentMetadata->table['indexes'] as $index) {
if (!$this->hasSameIndex($index, $classMetadata->table['indexes'])) {
$classMetadata->table['indexes'][] = $index;
}
}
foreach ($parentMetadata->table['uniqueConstraints'] as $uniqueConstraint) {
if (!$this->hasSameIndex($uniqueConstraint, $classMetadata->table['uniqueConstraints'])) {
$classMetadata->table['uniqueConstraints'][] = $uniqueConstraint;
}
}
}
private function hasSameIndex(array $needle, array $haystack): bool
{
foreach ($haystack as $item) {
if ($item['columns'] === $needle['columns']) {
return true;
}
}
return false;
}
}
#config/services.yaml
services:
App\EventListener\InheritIndexListener:
tags:
- { name: doctrine.event_listener, event: loadClassMetadata }
And entities.和实体。
#src/Entity/BaseResource.php
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\MappedSuperclass
* @ORM\Table(
* indexes={
* @ORM\Index(columns={"external_id"}),
* }
* )
*/
abstract class BaseResource
{
/**
* @var int|null
* @ORM\Column(type="integer")
*/
private $externalId;
//...
}
#src/Entity/BaseSlugableResource.php
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\MappedSuperclass
* @ORM\Table
* uniqueConstraints={
* @ORM\UniqueConstraint(columns={"slug"}),
* },
* )
*/
abstract class BaseSlugableResource extends BaseResource
{
/**
* @var string|null
* @ORM\Column(type="string")
*/
private $slug;
//...
}
#src/Entity/Article.php
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Article extends BaseSlugableResource
{
//...
}
In result the Article entity will have externalId index and slug unique index.结果,文章实体将具有 externalId 索引和 slug 唯一索引。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.