Edit

Inheritance Mapping

Doctrine currently offers two supported methods of inheritance: single collection and collection per class inheritance.

Mapped Superclasses

A mapped superclass is an abstract or concrete class that provides mapping information for its subclasses, but is not itself a document. Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple document classes.

Just like non-mapped classes, mapped superclasses may appear in the middle of an otherwise mapped inheritance hierarchy (through single collection or collection per class) inheritance.

A mapped superclass cannot be a document and is not queryable.

Example:

  • PHP
    1<?php namespace Documents; /** @MappedSuperclass */ abstract class BaseDocument { }
    2
    3
    4
    5
    6
    7
    8
  • XML
    1<?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <mapped-superclass name="Documents\BaseDocument"> </mapped-superclass> </doctrine-mongo-mapping>
    2
    3
    4
    5
    6
    7
    8
  • YAML
    1Documents\BaseDocument: type: mappedSuperclass
    2

Single Collection Inheritance

In single collection inheritance, each document is stored in a single collection and a discriminator field is used to distinguish one document type from another.

Simple example:

  • PHP
    1<?php namespace Documents; /** * @Document * @InheritanceType("SINGLE_COLLECTION") * @DiscriminatorField("type") * @DiscriminatorMap({"person"="Person", "employee"="Employee"}) */ class Person { // ... } /** * @Document */ class Employee extends Person { // ... }
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
  • XML
    1<?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Person" inheritance-type="SINGLE_COLLECTION"> <discriminator-field name="type" /> <discriminator-map> <discriminator-mapping value="person" class="Person" /> <discriminator-mapping value="employee" class="Employee" /> </discriminator-map> </document> </doctrine-mongo-mapping> <?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Employee"> </document> </doctrine-mongo-mapping>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
  • YAML
    1Documents\Person: type: document inheritanceType: SINGLE_COLLECTION discriminatorField: type discriminatorMap: person: Person employee: Employee
    2
    3
    4
    5
    6
    7

The discriminator value allows Doctrine to infer the class name to instantiate when hydrating a document. If a discriminator map is used, the discriminator value will be used to look up the class name in the map.

Now, if we query for a Person and its discriminator value is employee, we would get an Employee instance back:

1<?php $employee = new Employee(); // ... $dm->persist($employee); $dm->flush(); $employee = $dm->find('Person', $employee->getId()); // instanceof Employee
2
3
4
5
6
7
8

Even though we queried for a Person, Doctrine will know to return an Employee instance because of the discriminator map!

If your document structure has changed and you've added discriminators after already having a bunch of documents, you can specify a default value for the discriminator field:

  • PHP
    1<?php namespace Documents; /** * @Document * @InheritanceType("SINGLE_COLLECTION") * @DiscriminatorField("type") * @DiscriminatorMap({"person"="Person", "employee"="Employee"}) * @DefaultDiscriminatorValue("person") */ class Person { // ... } /** * @Document */ class Employee extends Person { // ... }
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
  • XML
    1<?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Person" inheritance-type="SINGLE_COLLECTION"> <discriminator-field name="type" /> <discriminator-map> <discriminator-mapping value="person" class="Person" /> <discriminator-mapping value="employee" class="Employee" /> </discriminator-map> <default-discriminator-value value="person" /> </document> </doctrine-mongo-mapping> <?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Employee"> </document> </doctrine-mongo-mapping>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
  • YAML
    1Documents\Person: type: document inheritanceType: SINGLE_COLLECTION discriminatorField: type defaultDiscriminatorValue: person discriminatorMap: person: Person employee: Employee
    2
    3
    4
    5
    6
    7
    8

Collection Per Class Inheritance

With collection per class inheritance, each document is stored in its own collection and contains all inherited fields:

  • PHP
    1<?php namespace Documents; /** * @Document * @InheritanceType("COLLECTION_PER_CLASS") */ class Person { // ... } /** * @Document */ class Employee extends Person { // ... }
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • XML
    1<?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Person" inheritance-type="COLLECTION_PER_CLASS"> </document> </doctrine-mongo-mapping> <?xml version="1.0" encoding="UTF-8"?> <doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> <document name="Documents\Employee"> </document> </doctrine-mongo-mapping>
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  • YAML
    1Documents\Person: type: document inheritanceType: COLLECTION_PER_CLASS
    2
    3

A discriminator is not needed with this type of inheritance since the data is separated in different collections.