You are browsing a version that has not yet been released.

Inheritance Mapping

Doctrine supports two approaches to inheritance:

  • Single collection inheritance, where all classes in the hierarchy are stored in the same collection and a discriminator field identifies each document type.
  • Sharing common fields across document classes stored in different collections, using PHP inheritance or traits.

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:

<?phpnamespace Documents;#[Document]#[InheritanceType('SINGLE_COLLECTION')]#[DiscriminatorField('type')]#[DiscriminatorMap(['person' => Person::class, 'employee' => Employee::class])]class Person{    // ...}#[Document]class Employee extends Person{    // ...}

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:

<?php$employee = new Employee();// ...$dm->persist($employee);$dm->flush();$employee = $dm->find(Person::class, $employee->getId()); // instanceof Employee

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:

<?phpnamespace Documents;#[Document]#[InheritanceType('SINGLE_COLLECTION')]#[DiscriminatorField('type')]#[DiscriminatorMap(['person' => Person::class, 'employee' => Employee::class])]#[DefaultDiscriminatorValue('person')]class Person{    // ...}#[Document]class Employee extends Person{    // ...}

Sharing Common Fields

To share common fields across multiple document classes stored in different collections, use a PHP abstract parent class or a trait. ODM reads field mappings from all properties of a class through reflection, whether they are declared in the class itself, a parent class, or a trait.

Each class is stored in its own collection. Unlike single collection inheritance, there is no discriminator field and documents are not polymorphically queryable across classes.

Abstract parent class

<?phpnamespace Documents;abstract class BaseDocument{    #[Field]    private string $createdBy;}#[Document(collection: 'articles')]class Article extends BaseDocument{    // inherits $createdBy}#[Document(collection: 'comments')]class Comment extends BaseDocument{    // inherits $createdBy}

PHP trait

<?phpnamespace Documents;trait Timestamps{    #[Field]    private DateTimeImmutable $createdAt;    #[Field]    private DateTimeImmutable $updatedAt;}#[Document(collection: 'articles')]class Article{    use Timestamps;}#[Document(collection: 'comments')]class Comment{    use Timestamps;}

Mapped Superclass

When using XML mapping, each class requires its own mapping file. To share fields from a parent class, declare it as a mapped-superclass so the driver knows to load its mapping file:

<?phpnamespace Documents;#[MappedSuperclass]abstract class BaseDocument{    #[Field]    private string $createdBy;}

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