You are browsing a version that is no longer maintained.

Basic Mapping

This chapter explains the basic mapping of objects and properties. Mapping of references and embedded documents will be covered in the next chapter "Reference Mapping".

Mapping Drivers

Doctrine provides several different ways for specifying object document mapping metadata:

If you're wondering which mapping driver gives the best performance, the answer is: None. Once the metadata of a class has been read from the source (Attributes or XML) it is stored in an instance of the Doctrine\ODM\MongoDB\Mapping\ClassMetadata class and these instances are stored in the metadata cache. Therefore all drivers perform equally well at runtime.

Introduction to Attributes

PHP attributes are a PHP 8+ feature that provides a native way to add metadata to classes, methods, properties, and other language constructs. They replace doctrine annotations by offering a standardized approach to metadata, eliminating the need for the separate parsing library required by annotations.

In this documentation we follow the PER Coding Style for attributes. We use named arguments for attributes as the names of their constructor arguments are covered by Doctrine Backward-Compatibility promise.

Doctrine Annotations are deprecated. You can migrate to PHP Attributes automatically using Rector.

Persistent classes

In order to mark a class for object-relational persistence it needs to be designated as a document. This can be done through the #[Document] marker attribute.

1<?php namespace Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations\Document; #[Document] class User { }
2
3
4
5
6
7
8
9
10

By default, the document will be persisted to a database named doctrine and a collection with the same name as the class name. In order to change that, you can use the db and collection option as follows:

1<?php namespace Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations\Document; #[Document(db: 'my_db', collection: 'users')] class User { }
2
3
4
5
6
7
8
9
10

Now instances of Documents\User will be persisted into a collection named users in the database my_db.

If you want to omit the db argument you can configure the default database to use with the setDefaultDB() method:

1<?php $config->setDefaultDB('my_db');
2
3

Doctrine Mapping Types

A Doctrine Mapping Type defines the mapping between a PHP type and a MongoDB type. You can even write your own custom mapping types.

Here is a quick overview of the built-in mapping types:

  • bin
  • bin_bytearray
  • bin_custom
  • bin_func
  • bin_md5
  • bin_uuid
  • bool
  • collection
  • custom_id
  • date
  • date_immutable
  • decimal128
  • file
  • float
  • hash
  • id
  • int
  • key
  • object_id
  • raw
  • string
  • timestamp

You can read more about the available MongoDB types on php.net.

The Doctrine mapping types are used to convert the local PHP types to the MongoDB types when persisting so that your domain is not bound to MongoDB-specific types. For example a DateTime instance may be converted to MongoDB\BSON\UTCDateTime when you persist your documents, and vice versa during hydration.

Generally, the name of each built-in mapping type hints as to how the value will be converted. This list explains some of the less obvious mapping types:

  • bin: string to MongoDBBSONBinary instance with a "generic" type (default)
  • bin_bytearray: string to MongoDBBSONBinary instance with a "byte array" type
  • bin_custom: string to MongoDBBSONBinary instance with a "custom" type
  • bin_func: string to MongoDBBSONBinary instance with a "function" type
  • bin_md5: string to MongoDBBSONBinary instance with a "md5" type
  • bin_uuid: string to MongoDBBSONBinary instance with a "uuid" type
  • collection: numerically indexed array to MongoDB array
  • date: DateTime to MongoDB\BSON\UTCDateTime
  • date_immutable: DateTimeImmutable to MongoDB\BSON\UTCDateTime
  • decimal128: string to MongoDB\BSON\Decimal128, requires ext-bcmath
  • hash: associative array to MongoDB object
  • id: string to ObjectId by default, but other formats are possible
  • timestamp: string to MongoDB\BSON\Timestamp
  • raw: any type

If you are using the hash type, values within the associative array are passed to MongoDB directly, without being prepared. Only formats suitable for the Mongo driver should be used. If your hash contains values which are not suitable you should either use an embedded document or use formats provided by the MongoDB driver (e.g. \MongoDB\BSON\UTCDateTime instead of \DateTime).

PHP Types Mapping

Doctrine will skip type autoconfiguration if settings are provided explicitly.

Since version 2.4 Doctrine can determine usable defaults from property types on document classes. Doctrine will map PHP types to type arguments as follows:

  • DateTime: date
  • DateTimeImmutable: date_immutable
  • array: hash
  • bool: bool
  • float: float
  • int: int
  • string: string

Doctrine can also autoconfigure any backed enum it encounters: type will be set to string or int, depending on the enum's backing type, and enumType to the enum's FQCN.

Nullable type does not imply nullable mapping option. You need to manually set nullable=true to have null values saved to the database.

Additionally Doctrine can determine collectionClass for ReferenceMany and EmbedMany collections from property's type.

Property Mapping

After a class has been marked as a document it can specify mappings for its instance fields. Here we will only look at simple fields that hold scalar values like strings, numbers, etc. References to other objects and embedded objects are covered in the chapter "Reference Mapping".

Identifiers

Every document class needs an identifier. You designate the field that serves as the identifier with the #[Id] marker attribute. Here is an example:

1<?php namespace Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations\Document; use Doctrine\ODM\MongoDB\Mapping\Annotations\Id; #[Document] class User { #[Id] public string $id; }
2
3
4
5
6
7
8
9
10
11
12
13

You can configure custom ID strategies if you don't want to use the default object ID. The available strategies are:

  • AUTO - Uses the native generated ObjectId.
  • ALNUM - Generates an alpha-numeric string (based on an incrementing value).
  • CUSTOM - Defers generation to an implementation of IdGenerator specified in the class option.
  • INCREMENT - Uses another collection to auto increment an integer identifier.
  • UUID - Generates a UUID identifier.
  • NONE - Do not generate any identifier. ID must be manually set.

Here is an example how to manually set a string identifier for your documents:

1<?php namespace Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations\Document; use Doctrine\ODM\MongoDB\Mapping\Annotations\Id; #[Document] class MyPersistentClass { #[Id(strategy: 'NONE', type: 'string')] public string $id; //... }
2
3
4
5
6
7
8
9
10
11
12
13
14
15

When using the NONE strategy you will have to explicitly set an id before persisting the document:

1<?php //... $document = new MyPersistentClass(); $document->setId('my_unique_identifier'); $dm->persist($document); $dm->flush();
2
3
4
5
6
7
8

Now you can retrieve the document later:

1<?php //... $document = $dm->find(MyPersistentClass::class, 'my_unique_identifier');
2
3
4
5

You can define your own ID generator by implementing the Doctrine\ODM\MongoDB\Id\IdGenerator interface:

1<?php namespace Vendor\Specific; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Id\IdGenerator; class Generator implements IdGenerator { public function generate(DocumentManager $dm, object $document) { // Your own logic here return 'my_generated_id'; } }
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Then specify the class option for the CUSTOM strategy:

1<?php #[Document] class MyPersistentClass { #[Id(strategy: 'CUSTOM', type: 'string', options: ['class' => \Vendor\Specific\Generator::class])] private string $id; public function setId(string $id): void { $this->id = $id; } //... }
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Fields

To mark a property to be persisted in the document, add the #[Field] attribute. The name and the type of the field are inferred from the property name and type.

Example:

1<?php namespace Documents; use Doctrine\ODM\MongoDB\Mapping\Annotations\Document; use Doctrine\ODM\MongoDB\Mapping\Annotations\Field; #[Document] class User { // ... #[Field] public string $username; }
2
3
4
5
6
7
8
9
10
11
12
13
14
15

In that example we mapped the property id to the field id using the mapping type id and the property name is mapped to the field name with the default mapping type string. To specify a different name for the field, you can use the name argument of the Field attribute as follows:

1<?php class User { #[Field(name: 'db_name')] public string $name; }
2
3
4
5
6
7

Date Fields

MongoDB has a specific database type to store date and time values. You should never use a string to store a date. To define a date field, use the property types DateTime or DateTimeImmutable so that Doctrine maps it to a BSON date. The date and date_immutable mapping types can be used explicitly; they are required only if the property type is DateTimeInterface or not set.

1<?php class User { #[Field] public \DateTimeImmutable $immutableDateTime; #[Field] public \DateTime $mutableDateTime; #[Field(type: 'date_immutable')] public \DateTimeInterface $datetime; }
2
3
4
5
6
7
8
9
10
11
12
13

Prefer using DateTimeImmutable over DateTime to avoid issues with mutable objects. If you need to modify a date, create a new instance and assign it to the property.

Multiple Document Types in a Collection

You can easily store multiple types of documents in a single collection. This requires specifying the same collection name, discriminatorField, and (optionally) discriminatorMap mapping options for each class that will share the collection. Here is an example:

1<?php #[Document(collection: 'my_documents')] #[DiscriminatorField('type')] #[DiscriminatorMap(['article' => Article::class, 'album' => Album::class])] class Article { // ... } #[Document(collection: 'my_documents')] #[DiscriminatorField('type')] #[DiscriminatorMap(['article' => Article::class, 'album' => Album::class])] class Album { // ... }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

All instances of Article and Album will be stored in the my_documents collection. You can query for the documents of a particular class just like you normally would and the results will automatically be limited based on the discriminator value for that class.

If you wish to query for multiple types of documents from the collection, you may pass an array of document class names when creating a query builder:

1<?php $query = $dm->createQuery([Article::class, Album::class]); $documents = $query->execute();
2
3
4

The above will return a cursor that will allow you to iterate over all Article and Album documents in the collections.