less than 1 minute read

In Symfony Cookbook How to Override any Part of a Bundle, it is written that you cannot override entity mappings and only attributes can be modified in superclasses. However, it is possible to hack you way through and register an Event Listener on loadClassMetadata that will rewrite the mapping on-the-fly. I would not qualify this as a good approach, but it is the only way I found.

A similar solution can be used for Doctrine ORM.

Here is an example, removing the uniqueness on emailCanonical of FOSUserBundle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
# ClassMetadataListener.php

namespace Acme\UserBundle\EventListener;

use Doctrine\ODM\MongoDB\Event\LoadClassMetadataEventArgs;

/**
 * Ran when Mongo metadata is loaded.
 */
class ClassMetadataListener
{
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();

        // Override FOS to not have unique emails
        if ($classMetadata->reflClass->name == 'FOS\UserBundle\Model\User') {
            foreach ($classMetadata->indexes as $i => $index) {
                if (count($index['keys']) === 1 && isset($index['keys']['emailCanonical'])) {
                    $classMetadata->indexes[$i]['options']['unique'] = false;
                    break;
                }
            }
        }
    }
}
1
2
3
4
5
6
# services.yml
services:
    acme.user.metadata_listener:
        class: Acme\UserBundle\EventListener\ClassMetadataListener
        tags:
            -  { name: doctrine_mongodb.odm.event_listener, event: loadClassMetadata }

View Gist