PHPackages                             strictlyphp/domantra - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. strictlyphp/domantra

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

strictlyphp/domantra
====================

A principled PHP toolkit for building DDD + CQRS services with clarity and structure.

0.0.9(1mo ago)03.6kMITPHPPHP &gt;=8.2CI passing

Since Aug 3Pushed 1mo agoCompare

[ Source](https://github.com/strictlyPHP/domantra)[ Packagist](https://packagist.org/packages/strictlyphp/domantra)[ RSS](/packages/strictlyphp-domantra/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (12)Versions (13)Used By (0)

Domantra
========

[](#domantra)

[![Coverage Status](https://camo.githubusercontent.com/8ebe9878e4f24c762653fa22deb20b0f27945ba1a806203893a734c17a1036c4/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f7374726963746c795048502f646f6d616e7472612f62616467652e7376673f6272616e63683d6d61696e)](https://coveralls.io/github/strictlyPHP/domantra?branch=main)[![CI Status](https://github.com/strictlyPHP/domantra/actions/workflows/test-main.yml/badge.svg)](https://github.com/strictlyPHP/domantra/actions/workflows/test-main.yml/badge.svg)[![Stable](https://camo.githubusercontent.com/6eef678f6b40b47b7a65d6eff5e4b20a573bc8f3d9bcf3feee9149100c597e60/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7374726963746c797068702f646f6d616e747261)](https://camo.githubusercontent.com/6eef678f6b40b47b7a65d6eff5e4b20a573bc8f3d9bcf3feee9149100c597e60/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7374726963746c797068702f646f6d616e747261)

A PHP library implementing Domain-Driven Design (DDD) patterns and CQRS architecture. Domantra provides a solid foundation for building scalable, maintainable applications following DDD principles with command and query separation.

Features
--------

[](#features)

- Command and Query Buses for CQRS
- Domain Event Dispatching
- Automatic DTO Caching (InMemory, Redis, Predis)
- Role-Based Property Access Control
- Paginated Query Support with DTO Expansion
- Pluggable Logging via PSR-3

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Composer 2.0+

Installation
------------

[](#installation)

```
composer require strictlyphp/domantra
```

Quick Start
-----------

[](#quick-start)

### 1. Define a Value Object ID

[](#1-define-a-value-object-id)

IDs must implement `\Stringable` for cache key resolution:

```
namespace App\ValueObject;

use StrictlyPHP\Domantra\ValueObject\StringValueObject;
use StrictlyPHP\Domantra\ValueObject\ValueObject;

class UserId implements StringValueObject
{
    public function __construct(private readonly string $id) {}

    public function __toString(): string { return $this->id; }
    public function jsonSerialize(): string { return $this->id; }
    public function equals(ValueObject $other): bool
    {
        return $other instanceof self && $this->id === $other->id;
    }
}
```

### 2. Create an Event

[](#2-create-an-event)

Events implement `EventInterface` and carry data only — no timestamps:

```
namespace App\Domain\User\Event;

use StrictlyPHP\Domantra\Command\EventInterface;
use App\ValueObject\UserId;

readonly class UserWasCreated implements EventInterface
{
    public function __construct(
        public UserId $id,
        public string $username,
        public string $email
    ) {}
}
```

### 3. Create a DTO

[](#3-create-a-dto)

DTOs implement `CachedDtoInterface` for automatic caching:

```
namespace App\Domain\User;

use StrictlyPHP\Domantra\Domain\CachedDtoInterface;
use App\ValueObject\UserId;

readonly class UserDto implements CachedDtoInterface
{
    public function __construct(
        public UserId $id,
        public string $username,
        public string $email
    ) {}

    public function getCacheKey(): string { return (string) $this->id; }
    public function getTtl(): int { return 3600; }
}
```

### 4. Build the Aggregate Root

[](#4-build-the-aggregate-root)

```
namespace App\Domain\User;

use StrictlyPHP\Domantra\Domain\AbstractAggregateRoot;
use StrictlyPHP\Domantra\Domain\UseTimestamps;
use App\ValueObject\UserId;
use App\Domain\User\Event\UserWasCreated;

#[UseTimestamps]
class User extends AbstractAggregateRoot
{
    private UserId $id;
    private string $username;
    private string $email;

    public static function create(
        UserId $id,
        string $username,
        string $email,
        \DateTimeImmutable $happenedAt
    ): self {
        $user = new self();
        $user->recordAndApplyThat(
            new UserWasCreated($id, $username, $email),
            $happenedAt
        );
        return $user;
    }

    protected function applyThatUserWasCreated(UserWasCreated $event): void
    {
        $this->id = $event->id;
        $this->username = $event->username;
        $this->email = $event->email;
    }

    public function getDto(): UserDto
    {
        return new UserDto($this->id, $this->username, $this->email);
    }
}
```

### 5. Command &amp; Handler

[](#5-command--handler)

```
namespace App\Domain\User\Command;

use StrictlyPHP\Domantra\Command\CommandInterface;
use App\ValueObject\UserId;

class CreateUserCommand implements CommandInterface
{
    public function __construct(
        public readonly UserId $id,
        public readonly string $username,
        public readonly string $email,
        public readonly \DateTimeImmutable $happenedAt
    ) {}
}
```

```
namespace App\Domain\User\Command;

use App\Domain\User\User;

class CreateUserHandler
{
    public function __invoke(CreateUserCommand $command): User
    {
        $user = User::create(
            $command->id,
            $command->username,
            $command->email,
            $command->happenedAt
        );

        // Persist the user (e.g., save to database)

        return $user;
    }
}
```

### 6. Dispatch via Command Bus

[](#6-dispatch-via-command-bus)

```
use StrictlyPHP\Domantra\Command\CommandBus;
use App\Domain\User\Command\CreateUserCommand;
use App\Domain\User\Command\CreateUserHandler;
use App\ValueObject\UserId;

$commandBus = CommandBus::create();
$commandBus->registerHandler(CreateUserCommand::class, new CreateUserHandler());

$commandBus->dispatch(new CreateUserCommand(
    new UserId('user-123'),
    'john_doe',
    'john@example.com',
    new \DateTimeImmutable()
));
```

The bus automatically dispatches events and caches the DTO.

### 7. Query Handling

[](#7-query-handling)

```
namespace App\Domain\User\Query;

use StrictlyPHP\Domantra\Query\Handlers\SingleHandlerInterface;
use App\Domain\User\User;

class GetUserByIdHandler implements SingleHandlerInterface
{
    public function __invoke(object $query): User
    {
        // Fetch user from database by $query (a UserId)
        // Return the reconstructed aggregate root
    }
}
```

```
use StrictlyPHP\Domantra\Query\QueryBus;
use StrictlyPHP\Domantra\Query\AggregateRootHandler;
use StrictlyPHP\Domantra\Query\CachedDtoHandler;
use StrictlyPHP\Domantra\Cache\DtoCacheHandlerInMemory;
use App\ValueObject\UserId;

$cacheHandler = new DtoCacheHandlerInMemory();
$queryBus = new QueryBus(
    new AggregateRootHandler($cacheHandler),
    new CachedDtoHandler($cacheHandler)
);

$queryBus->registerHandler(UserId::class, new GetUserByIdHandler());

$response = $queryBus->handle(new UserId('user-123'));
// Returns ModelResponse with $response->item
```

The query bus checks the cache first. On a miss, it invokes the handler, caches the DTO, and returns it.

Testing
-------

[](#testing)

All commands run inside Docker — no local PHP extensions are required.

```
make install           # Install dependencies
make check-coverage    # Run tests with coverage check on changed files
make style             # Check coding style
make style-fix         # Auto-fix coding style
make analyze           # Run static analysis (PHPStan)
```

Run `make help` to see all available commands.

Documentation
-------------

[](#documentation)

For detailed guides on all features, see the [docs/](docs/README.md) directory:

- [Installation](docs/installation.md)
- [Value Objects](docs/value-objects.md)
- [Aggregate Roots](docs/aggregate-roots.md)
- [Events](docs/events.md)
- [DTOs &amp; Caching](docs/dtos-and-caching.md)
- [Commands](docs/commands.md)
- [Queries](docs/queries.md) — pagination, expansion, handler types
- [Role-Based Access](docs/role-based-access.md)
- [Clock](docs/clock.md) — time abstraction for testing

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance88

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.2% 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 ~33 days

Total

8

Last Release

58d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d03651fbb8a8c8e87446a872b0a21a4fb80589227bd3bf6802523f553992d53b?d=identicon)[lalobo](/maintainers/lalobo)

---

Top Contributors

[![lalobo](https://avatars.githubusercontent.com/u/736300?v=4)](https://github.com/lalobo "lalobo (60 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (3 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleECS

Type Coverage Yes

### Embed Badge

![Health badge](/badges/strictlyphp-domantra/health.svg)

```
[![Health](https://phpackages.com/badges/strictlyphp-domantra/health.svg)](https://phpackages.com/packages/strictlyphp-domantra)
```

###  Alternatives

[grumpydictator/firefly-iii

Firefly III: a personal finances manager.

22.8k69.3k](/packages/grumpydictator-firefly-iii)[blair2004/nexopos

The Free Modern Point Of Sale System build with Laravel, TailwindCSS and Vue.js.

1.2k2.3k](/packages/blair2004-nexopos)

PHPackages © 2026

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