Model » Lifecycle hooks

Run custom logic — or veto an operation entirely — at key points in a model's lifecycle.

About lifecycle hooks

MondocAbstractModel exposes six hook methods that fire around the three mutating operations: insert, update, and delete. Each pair consists of a before* hook that can cancel the operation by returning false, and an after* hook that runs once the operation has completed successfully.

All six hooks have default no-op implementations in MondocAbstractModel, so you only need to override the ones you care about.

Hook methods

  • beforeInsert(): bool
    Called before this model is inserted. Return false to cancel the insert; the service method will return false without persisting the document.
  • afterInsert(): void
    Called after this model has been successfully inserted. The model will already have its ObjectId assigned at this point.
  • beforeUpdate(): bool
    Called before this model is updated. Return false to cancel the update; the service method will return false without persisting any changes.
  • afterUpdate(): void
    Called after this model has been successfully updated.
  • beforeDelete(): bool
    Called before this model is deleted. Return false to cancel the deletion; the service method will return false without removing the document.
  • afterDelete(): void
    Called after this model has been successfully deleted. The model's ObjectId will have been unset at this point.

Example

The example below shows a model that uses hooks to validate data before insertion, stamp an audit log after updates, and prevent active records from being deleted.

<?php
use District5\Mondoc\Db\Model\MondocAbstractModel;

class MyModel extends MondocAbstractModel
{
    protected string $name = '';
    protected bool $active = true;

    // Prevent inserting a model with an empty name
    public function beforeInsert(): bool
    {
        return $this->name !== '';
    }

    // Stamp a modification time after every successful update
    public function afterUpdate(): void
    {
        // e.g. log the change, dispatch an event, notify a subscriber...
    }

    // Prevent deleting active records
    public function beforeDelete(): bool
    {
        return !$this->active;
    }
}

$model = new MyModel();
$model->setName(''); // empty name
$model->save(); // returns false — beforeInsert vetoed the insert

$model->setName('Alice');
$model->save(); // returns true — inserted successfully

Hooks and insertMulti()

Hooks fire per-model when using insertMulti(). Any model whose beforeInsert() returns false is silently skipped; the remaining models are inserted as a single batch. afterInsert() is called on each model that was successfully inserted.

<?php
$alice = new MyModel();
$alice->setName('Alice');

$noName = new MyModel();
// setName not called — beforeInsert() will veto this one

MyService::insertMulti([$alice, $noName]);
// $alice is inserted:  $alice->hasObjectId() === true
// $noName is skipped:  $noName->hasObjectId() === false