Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine 2 Index Inheritance

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.

like image 319
Harry Avatar asked Dec 13 '13 02:12

Harry


1 Answers

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 }
like image 194
Thomas Landauer Avatar answered Sep 28 '22 14:09

Thomas Landauer