Embedded Mapping

This chapter explains how embedded documents are mapped in Doctrine.

Embed One

Embed a single document:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ...
    
        /** @EmbedOne(targetDocument="Address") */
        private $address;
    
        // ...
    }
    
    /** @EmbeddedDocument */
    class Address
    {
        // ...
    }
    
  • 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\User">
            <embed-one field="address" target-document="Address" />
      </document>
    </doctrine-mongo-mapping>
    
  • YAML
    User:
      type: document
      embedOne:
        address:
          targetDocument: Address
    
    Address:
      type: embeddedDocument
    

Embed Many

Embed many documents:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ...
    
        /** @EmbedMany(targetDocument="Phonenumber") */
        private $phonenumbers = array();
    
        // ...
    }
    
    /** @EmbeddedDocument */
    class Phonenumber
    {
        // ...
    }
    
  • 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\User">
            <embed-many field="phonenumbers" target-document="Phonenumber" />
      </document>
    </doctrine-mongo-mapping>
    
  • YAML
    User:
      type: document
      embedMany:
        phonenumbers:
          targetDocument: Phonenumber
    
    Phonenumber:
      type: embeddedDocument
    

Mixing Document Types

If you want to store different types of embedded documents in the same field, you can simply omit the targetDocument option:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ..
    
        /** @EmbedMany */
        private $tasks = array();
    
        // ...
    }
    
  • XML
    <embed-many field="tasks" />
    
  • YAML
    embedMany:
      tasks: ~
    

Now the $tasks property can store any type of document! The class name will be automatically stored in a field named _doctrine_class_name within the embedded document. The field name can be customized with the discriminatorField option:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ..
    
        /**
         * @EmbedMany(discriminatorField="type")
         */
        private $tasks = array();
    
        // ...
    }
    
  • XML
    <embed-many field="tasks">
        <discriminator-field name="type" />
    </embed-many>
    
  • YAML
    embedMany:
      tasks:
        discriminatorField: type
    

You can also specify a discriminator map to avoid storing the |FQCN| in each embedded document:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ..
    
        /**
         * @EmbedMany(
         *   discriminatorMap={
         *     "download"="DownloadTask",
         *     "build"="BuildTask"
         *   }
         * )
         */
        private $tasks = array();
    
        // ...
    }
    
  • XML
    <embed-many field="tasks">
        <discriminator-map>
            <discriminator-mapping value="download" class="DownloadTask" />
            <discriminator-mapping value="build" class="BuildTask" />
        </discriminator-map>
    </embed-many>
    
  • YAML
    embedMany:
      tasks:
        discriminatorMap:
          download: DownloadTask
          build: BuildTask
    

If you have embedded documents without a discriminator value that need to be treated correctly you can optionally specify a default value for the discriminator:

  • PHP
    <?php
    
    /** @Document */
    class User
    {
        // ..
    
        /**
         * @EmbedMany(
         *   discriminatorMap={
         *     "download"="DownloadTask",
         *     "build"="BuildTask"
         *   },
         *   defaultDiscriminatorValue="download"
         * )
         */
        private $tasks = array();
    
        // ...
    }
    
  • XML
    <embed-many field="tasks">
        <discriminator-map>
            <discriminator-mapping value="download" class="DownloadTask" />
            <discriminator-mapping value="build" class="BuildTask" />
        </discriminator-map>
        <default-discriminator-value value="download" />
    </embed-many>
    
  • YAML
    embedMany:
      tasks:
        discriminatorMap:
          download: DownloadTask
          build: BuildTask
        defaultDiscriminatorValue: download
    

Cascading Operations

All operations on embedded documents are automatically cascaded. This is because embedded documents are part of their parent document and cannot exist without those by nature.

Fork me on GitHub