Model » Nested models
Mondoc supports nested models, which are models that are contained within another model. This feature is useful when you need to represent complex data in your MongoDB documents.
Nesting objects by using the MondocAbstractSubModel
The MondocAbstractSubModel is actually the base class for all models in Mondoc. It ultimately provides the ability to inflate and deflate models into a suitable format for MongoDB.
Did you know: Nested models also support nested models. This means you can have a nested model which contains a nested model, which contains a nested model, and so on, and so forth.
Nested models can be either a singular model or an array of models. This is determined by the $mondocNested property in the top level model.
Consider the following example. We have a generic Person model, which does not extend the MondocAbstractModel class. Instead, it simply extends the MondocAbstractSubModel class.
<?php use District5\Mondoc\Db\Model\MondocAbstractSubModel; class Person extends MondocAbstractSubModel { protected string|null $name = null; public function getName(): string|null { return $this->name; } public function setName(string $name): void { $this->name = $name; } }
To use the above Person model as a nested model in a top level model (e.g. CompanyModel), you need to define the nested model in the top level model. The $mondocNested property is used to declare this relationship.
<?php use District5\Mondoc\Db\Model\MondocAbstractModel; use Person; class CompanyModel extends MondocAbstractModel { protected Person|null $boss = null; // Single Person model protected array $people = []; // Array of Person models protected array $mondocNested = [ 'boss' => Person::class, // Single nested model 'people' => Person::class . '[]' // Array of nested models ]; public function getBoss(): Person|null { return $this->boss; } public function setBoss(Person $boss): void { $this->boss = $boss; } public function getPeople(): array { return $this->people; } public function setPeople(array $people): void { $this->people = $people; } }
Flexible nested models
The need may arise for you to handle different models within the same field, for example in the case of an eCommerce store. MondocAbstractSubModel supports this by overriding the getMondocNestedModelMap method.
Please note:
This feature has been supported since 6.6.0.
Implementing the getMondocNestedModelMap method is optional, but overrides the requirement of the $mondocNested property entirely, therefore you must not use both.
Take the following nested models as an example, depending on your chosen provider, you can easily control the nested model class that is used.
Despite the following being against a single model, you can still alter these easily to become multiple
models, by appending []
to the defined class name.
<?php namespace My\Models\Gateways; use District5\Mondoc\Db\Model\MondocAbstractSubModel; class Stripe extends MondocAbstractSubModel { // Stripe specific fields }
<?php namespace My\Models\Gateways; use District5\Mondoc\Db\Model\MondocAbstractSubModel; class Worldpay extends MondocAbstractSubModel { // Worldpay specific fields }
Flexibility means you can define the nested model class at runtime, which is useful when you have different model providers for different environments.
<?php namespace My\Models; use District5\Mondoc\Db\Model\MondocAbstractModel; use My\Models\Gateways\Stripe; use My\Models\Gateways\Worldpay; class CustomerPayment extends MondocAbstractModel { protected Stripe|Worldpay|null $paymentGateway = null; /** * @return array */ public function getMondocNestedModelMap(): array { return [ 'paymentGateway' => getenv('PAYMENT_GATEWAY') === 'stripe' ? Stripe::class : Worldpay::class ]; } }