Inheritance Mapping

Doctrine currently offers two supported methods of inheritance which are Single Collection Inheritance and Collection Per Class Inheritance.

Mapped Superclasses

An mapped superclass is an abstract or concrete class that provides persistent document state and mapping information for its subclasses, but which 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.

Mapped superclasses, just as regular, non-mapped classes, can appear in the middle of an otherwise mapped inheritance hierarchy (through Single Collection Inheritance or Collection Per Class Inheritance).

Note

A mapped superclass cannot be a document and is not query able.

Example:

  • PHP
    <?php
    
    namespace Documents;
    
    /** @MappedSuperclass */
    abstract class BaseDocument
    {
    }
    
  • XML
    <?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>
    
  • YAML
    Documents\BaseDocument:
        type: mappedSuperclass
    

Single Collection Inheritance

In Single Collection Inheritance each document is stored in a single collection where a discriminator field is used to distinguish one document type from another.

Simple example:

  • PHP
    <?php
    
    namespace Documents;
    
    /**
     * @Document
     * @InheritanceType("SINGLE_COLLECTION")
     * @DiscriminatorField(fieldName="type")
     * @DiscriminatorMap({"person"="Person", "employee"="Employee"})
     */
    class Person
    {
        // ...
    }
    
    /**
     * @Document
     */
    class Employee extends Person
    {
        // ...
    }
    
  • XML
    <?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=" fieldName="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>
    
  • YAML
    Documents\Person:
      type: document
      inheritanceType: SINGLE_COLLECTION
      discriminatorMap:
        person: Person
        employee: Employee
    

The discriminator field value allows Doctrine to know what type of class to return by looking it up in the discriminator map. Now if we ask for a certain Person and it has a discriminator field value of employee, we would get an Employee instance back:

<?php

$employee = new Employee();
// ...
$dm->persist($employee);
$dm->flush();

$employee = $dm->find('Person', $employee->getId()); // instanceof Employee

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

Collection Per Class Inheritance

With Collection Per Class Inheritance each document is stored in its own collection and contains all inherited fields:

  • PHP
    <?php
    
    namespace Documents;
    
    /**
     * @Document
     * @InheritanceType("COLLECTION_PER_CLASS")
     */
    class Person
    {
        // ...
    }
    
    /**
     * @Document
     */
    class Employee extends Person
    {
        // ...
    }
    
  • XML
    <?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>
    
  • YAML
    Documents\Person:
      type: document
      inheritanceType: COLLECTION_PER_CLASS
    

In this type of inheritance a discriminator is not needed since the data is separated in different collections!




Fork me on GitHub