Doctrine 2 Index Inheritance
doctrine-orm, indexing, inheritance, php
Solution
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
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:
App\EventListener\MemberIndexListener:
tags:
- { name: doctrine.event_listener, event: loadClassMetadata }
Problem
i am new to Doctrine 2 am i trying to figure out how to do index inheritance with it. 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. 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. Hoping that this will result in 2 indexes for `Member` which is `created_on` and `email_address`+`password` combination. This however results in indexes of the base class being overriden by the child class, thus `created_on` is not an index. ``` /** * @MappedSuperclass * @Table(indexes={@Index(name="timestampcreated", columns={"created_on"})}) */ abstract class EntityAbstract ``` How do i achieve this in Doctrine 2? Have looked at single table inheritance, but my understanding is that it's meant for different purpose.