This chapter explains how embedded documents are mapped in
Doctrine.
Embed a single document:
Php
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\User" >
<embed-one field ="address" target-document ="Address" />
</document >
<embedded-document name ="Address" >
<field name ="street" type ="string" />
</embedded-document >
</doctrine-mongo-mapping >
2
3
4
5
6
7
8
9
10
11
12
13
Embed many documents:
Php
Xml
1 <?php
use Doctrine \Common \Collections \ArrayCollection ;
class User
{
private Collection $phoneNumbers;
public function __construct ()
{
$this ->phoneNumbers = new ArrayCollection();
}
}
class PhoneNumber
{
private string $number;
}
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
28
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\User" >
<embed-many field ="phoneNumbers" target-document ="PhoneNumber" />
</document >
<embedded-document name ="PhoneNumber" >
<field name ="number" type ="string" />
</embedded-document >
</doctrine-mongo-mapping >
2
3
4
5
6
7
8
9
10
11
12
13
If you want to store different types of embedded documents in the same field,
you can simply omit the targetDocument
option:
Php
Xml
1 <?php
use Doctrine \Common \Collections \ArrayCollection ;
class User
{
private Collection $tasks;
public function __construct ()
{
$this ->tasks = new ArrayCollection();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1 <embed-many field ="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
Xml
1 <?php
use Doctrine \Common \Collections \ArrayCollection ;
class User
{
private Collection $tasks;
public function __construct ()
{
$this ->tasks = new ArrayCollection();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1 <embed-many field ="tasks" >
<discriminator-field name ="type" />
</embed-many >
2
3
You can also specify a discriminator map to avoid storing the FQCN
in each embedded document:
Php
Xml
1 <?php
use Doctrine \Common \Collections \ArrayCollection ;
class User
{
discriminatorMap: [
'download' => DownloadTask::class,
'build' => BuildTask::class,
]
)]
private Collection $tasks;
public function __construct ()
{
$this ->tasks = new ArrayCollection();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1 <embed-many field ="tasks" >
<discriminator-map >
<discriminator-mapping value ="download" class ="DownloadTask" />
<discriminator-mapping value ="build" class ="BuildTask" />
</discriminator-map >
</embed-many >
2
3
4
5
6
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
Xml
1 <?php
class User
{
discriminatorMap: [
'download' => DownloadTask::class,
'build' => BuildTask::class,
],
defaultDiscriminatorValue: 'download' ,
)]
private Collection $tasks;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1 <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 >
2
3
4
5
6
7
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.
By default, when an embedded collection property is empty, Doctrine does not store any data for it in the database.
However, in some cases, you may want to explicitly store an empty array for such properties.
You can achieve this behavior by using the storeEmptyArray
option for embedded collections.
Php
Xml
1 <?php
class User
{
private Collection $phoneNumbers;
}
2
3
4
5
6
7
8
9
10
11
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\User" >
<embed-many field ="phoneNumbers" target-document ="PhoneNumber" store-empty-array ="true" />
</document >
<embedded-document name ="PhoneNumber" >
<field name ="number" type ="string" />
</embedded-document >
</doctrine-mongo-mapping >
2
3
4
5
6
7
8
9
10
11
12
Now, when the $phoneNumbers
collection is empty, an empty array will be stored in the database for the User
document's embedded phoneNumbers
collection, even if there are no actual embedded documents in the collection.