PHPackages                             magomogo/domain-model - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. magomogo/domain-model

ActiveLibrary[Database &amp; ORM](/categories/database)

magomogo/domain-model
=====================

A way to make domain-specific models persistent

v3.0.0(3y ago)711.4k↓25%6[1 issues](https://github.com/Magomogo/persisted-models/issues)MITPHPPHP ^7.1 || ^8.0CI failing

Since Dec 12Pushed 1y ago1 watchersCompare

[ Source](https://github.com/Magomogo/persisted-models)[ Packagist](https://packagist.org/packages/magomogo/domain-model)[ Docs](https://github.com/Magomogo/persisted-models)[ RSS](/packages/magomogo-domain-model/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (3)Dependencies (5)Versions (18)Used By (0)

Persisted models
================

[](#persisted-models)

[![Build Status](https://camo.githubusercontent.com/75ae744054018ea251c4acb9dc5d06a4c232f0bac87b923511f5fc56510a8cc6/68747470733a2f2f7472617669732d63692e6f72672f4d61676f6d6f676f2f7065727369737465642d6d6f64656c732e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/Magomogo/persisted-models)

Intro
-----

[](#intro)

- I don't like ActiveRecord because of tight coupling with the database,
- I am not so comfortable with Data mappers because a mapper breaks model encapsulation,
- I like the idea to keep **'The State'** separately from the logic.

Here is the way
---------------

[](#here-is-the-way)

### The concept

[](#the-concept)

To implement an entity, one should create two classes: **Model** and **Properties**. Model class contains domain-specific logic only. All **state** that should persist is located in **Properties**. Model has its Properties aggregated:

```
class Model implements ModelInterface
{
    /**
     * @var Properties
     */
    private $properties;

    public function __construct($properties)
    {
         $this->properties = $properties;
    }
}

```

This library takes care about the **Properties**, all its public fields and also relations can be saved/loaded in the **Container**s. Currently there is SqlDb, CouchDb, and Memory container.

It is recommended to declare Model's constructor signature that doesn't allow to create an instance that makes no sense from the business logic point of view.

```
$person = new Person\Model($propertiesBag);
$employee = new Employee\Model($company, $propertiesBag);

```

source: [Person\\Model](//github.com/Magomogo/persisted-models/blob/master/test/_classes/Magomogo/Persisted/Test/Person/Model.php "Person model")| [Employee\\Model](//github.com/Magomogo/persisted-models/blob/master/test/_classes/Magomogo/Persisted/Test/Employee/Model.php "Employee model")

### Obvious responsibilities

[](#obvious-responsibilities)

To achieve persistency we don't need to store **A model**, it is necessary to store its properties.

```
// save/update
$dbContainer = new Persisted\Container\SqlDb($connection);
$person->save($dbContainer);

// load
$persistedPerson = Person\Model::load($dbContainer, $id);

```

source: [Persisted\\Container\\SqlDb](//github.com/Magomogo/persisted-models/blob/master/lib/Magomogo/Persisted/Container/SqlDb.php "Database container")

Handling user input with **'Editors'**, **'A Editor'** is kind of a Container.

```
$editor = new ProfileEditor($person);
// validation here
$editor->edit($userInput);

$editedPerson = Person\Model::load($editor);
$editedPerson->save($dbContainer);

```

### Strong separation between different types of object relations

[](#strong-separation-between-different-types-of-object-relations)

For example person properties can have contact info aggregated, it gets stored and updated together with person:

```
$contactInfoModel = new ContactInfo\Model($contactInfoProperties);

$personProperties = array(
    'name' => 'John',
    'contactInfo => $contactInfoModel
);

```

On the other hand, there is a person who's working in a company. These objects are connected by foreign key and created/updated separately.

```
$company->save($dbContainer);
$employee = new Employee\Model($company, $employeeProperties);

// this won't update the company, but create one-to-many reference company -> person in the container
$employee->save($dbContainer);

```

A model can have a list of another models connected. This so-called many-to-many relation is possible using Collections.

```
$collection = new Keymarker\Collection;
$collection['Example'] = new Keymarker\Model(new Keymarker\Properties(array('name' => 'Example'));

```

Examples
--------

[](#examples)

See test cases to learn recommended usage:

- Simply a Model with properties [Company/ModelTest.php](//github.com/Magomogo/persisted-models/blob/master/test/Company/ModelTest.php)
- A Person having CreditCard aggregated, a Person that can be tagged with Keymarkers [Person/ModelTest.php](//github.com/Magomogo/persisted-models/blob/master/test/Person/ModelTest.php)
- An Employee working in a Company [Employee/ModelTest.php](//github.com/Magomogo/persisted-models/blob/master/test/Employee/ModelTest.php)
- Keymarker model that has natural keys [Keymarker/ModelTest.php](//github.com/Magomogo/persisted-models/blob/master/test/Keymarker/ModelTest.php), [Keymarker/PropertiesTest.php](//github.com/Magomogo/persisted-models/blob/master/test/Keymarker/PropertiesTest.php)
- Load/Create/Update/Save a persistent model [ModelPersonEditorWorkflowTest.php](//github.com/Magomogo/persisted-models/blob/master/test/ModelPersonEditorWorkflowTest.php)

*...the work is in progress...*

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance31

Infrequent updates — may be unmaintained

Popularity32

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 92.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~285 days

Recently: every ~469 days

Total

14

Last Release

1148d ago

Major Versions

0.8.x-dev → v1.0.02016-09-10

v1.0.1 → v2.0.02018-08-03

v2.0.2 → v3.0.02023-03-28

PHP version history (3 changes)0.1.x-devPHP &gt;=5.3.0

v2.0.0PHP &gt;=5.6.0

v3.0.0PHP ^7.1 || ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/3b278f373383905fadd1bfdee771c682805638284672681cd5d912e74cb794ad?d=identicon)[Magomogo](/maintainers/Magomogo)

---

Top Contributors

[![Magomogo](https://avatars.githubusercontent.com/u/728657?v=4)](https://github.com/Magomogo "Magomogo (206 commits)")[![smoskalenko](https://avatars.githubusercontent.com/u/13538100?v=4)](https://github.com/smoskalenko "smoskalenko (10 commits)")[![zebooka](https://avatars.githubusercontent.com/u/2102717?v=4)](https://github.com/zebooka "zebooka (5 commits)")[![ZWalrus](https://avatars.githubusercontent.com/u/2705962?v=4)](https://github.com/ZWalrus "ZWalrus (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/magomogo-domain-model/health.svg)

```
[![Health](https://phpackages.com/badges/magomogo-domain-model/health.svg)](https://phpackages.com/packages/magomogo-domain-model)
```

###  Alternatives

[scienta/doctrine-json-functions

A set of extensions to Doctrine that add support for json query functions.

58723.9M36](/packages/scienta-doctrine-json-functions)[martin-georgiev/postgresql-for-doctrine

Extends Doctrine with native PostgreSQL support for arrays, JSONB, ranges, PostGIS geometries, text search, ltree, uuid, and 100+ PostgreSQL-specific functions.

4485.3M4](/packages/martin-georgiev-postgresql-for-doctrine)[damienharper/auditor-bundle

Integrate auditor library in your Symfony projects.

4542.8M](/packages/damienharper-auditor-bundle)[sonata-project/entity-audit-bundle

Audit for Doctrine Entities

644989.8k1](/packages/sonata-project-entity-audit-bundle)[overtrue/laravel-versionable

Make Laravel model versionable.

585308.0k5](/packages/overtrue-laravel-versionable)[worksome/foggy

Foggy is a tool for making database dumps with some data removed/changed.

26571.7k1](/packages/worksome-foggy)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
