PHPackages                             fusonic/ddd-extensions - 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. [Framework](/categories/framework)
4. /
5. fusonic/ddd-extensions

ActiveLibrary[Framework](/categories/framework)

fusonic/ddd-extensions
======================

Symfony domain-driven design building blocks for usage with Doctrine ORM.

3.0.2(5mo ago)112.0k↓32.7%1MITPHPPHP &gt;=8.2

Since Apr 26Pushed 5mo ago6 watchersCompare

[ Source](https://github.com/fusonic/php-ddd-extensions)[ Packagist](https://packagist.org/packages/fusonic/ddd-extensions)[ RSS](/packages/fusonic-ddd-extensions/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (16)Versions (23)Used By (1)

ddd-extensions
==============

[](#ddd-extensions)

[![License](https://camo.githubusercontent.com/bec2e097bcbba8164856cf56fe59743e354a6a6b24ea81b206890d08abed6a8e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6675736f6e69632f6464642d657874656e73696f6e733f636f6c6f723d626c7565)](https://github.com/fusonic/php-ddd-extensions/blob/master/LICENSE)[![Latest Version](https://camo.githubusercontent.com/755dcf50846c8a6d6c933225f5ed36c441d169b2f94c3fa4a3cdae8e235298e3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f7461672f6675736f6e69632f7068702d6464642d657874656e73696f6e732e7376673f636f6c6f723d626c7565)](https://github.com/fusonic/php-ddd-extensions/releases)[![Total Downloads](https://camo.githubusercontent.com/038404172ba63a1c4df1a4933e7dcfd4daa5fe9e197693ded71f185e1e12226f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6675736f6e69632f6464642d657874656e73696f6e732e7376673f636f6c6f723d626c7565)](https://packagist.org/packages/fusonic/ddd-extensions)[![php 8.2+](https://camo.githubusercontent.com/2acc9abf8a0687f1ee2c8f864ea70eb248731b91e8878d481f733ed115157ad1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d6d696e253230382e322d626c75652e737667)](https://github.com/fusonic/php-ddd-extensions/blob/master/composer.json)

- [About](#about)
- [Install](#install)
- [Configuration](#configuration)
- [Usage and recommendations](#usage-and-recommendations)

About
-----

[](#about)

This library provides some base classes for implementing a domain driven design in PHP. Helpful tools are provided for usage with Symfony and Doctrine, however you are not required to use those.

Install
-------

[](#install)

Use composer to install the lib from packagist.

```
composer require fusonic/ddd-extensions
```

Configuration
-------------

[](#configuration)

```
services:
    # This service dispatches the domain events raised on aggregate roots to the given message bus.
    Fusonic\DDDExtensions\Doctrine\LifecycleListener\DomainEventLifecycleListener:
        arguments:
            $bus: '@Symfony\Component\Messenger\MessageBusInterface'
        tags:
            # Note: The listener has to be tagged individually for each event
            - { name: doctrine.event_listener, event: 'postPersist', priority: 500 }
            - { name: doctrine.event_listener, event: 'postUpdate', priority: 500 }
            - { name: doctrine.event_listener, event: 'postRemove', priority: 500 }
            - { name: doctrine.event_listener, event: 'postFlush', priority: 500 }

    # Optionally configure a ModelDescriber if you are using NelmioApiDocBundle to display EntityId objects in the
    # generated documentation
    Fusonic\DDDExtensions\ModelDescriber\EntityIdDescriber:
        tags:
            - { name: nelmio_api_doc.model_describer, priority: 1000 }

    # Optionally configure a normalizer to automatically serialize/deserialize AbstractIntegerId objects
    Fusonic\DDDExtensions\Normalizer\EntityIdNormalizer:
        tags:
            - { name: serializer.normalizer }
```

Usage and recommendations
-------------------------

[](#usage-and-recommendations)

For an example, see the [examples in the tests](./tests/Domain).

### Value objects

[](#value-objects)

Value objects must extend `Fusonic\DDDExtensions\Domain\Model\ValueObject`. Value objects must be immutable. All the properties that it needs must be set when initiating the object. The value object can not have any setter properties.

For comparing value objects you must implement the `equals` function.

### Aggregate roots

[](#aggregate-roots)

Aggregate roots are the *entry points* to the bounded context. Domain objects that extend `Fusonic\DDDExtensions\Domain\Model\AggregateRoot`are aggregate roots. Only the aggregate roots can be created/modified directly outside of the bounded contexts. All sub-entities are modified/created through the aggregate root.

### Domain entities

[](#domain-entities)

Domain entities must implement `Fusonic\DDDExtensions\Domain\Model\EntityInterface`.

You should not do operations on domain entities (that are not aggregate roots) directly. Everything should go through the aggregate root.

The "id" returned by `getId()` can return anything, however it is recommended to create a dedicated "id" class for each domain entity. For example a `User` class with a `UserId` class. The `EntityId` extended class must implement a `__toString` method and a `getValue()` method which will return the internal value. The implementation of the internal value is up to you. For Doctrine you could use an integer and use the `Fusonic\DDDExtensions\Domain\Model\EntityIntegerId` class as a base class, see [this example](./tests/Domain/UserId.php).

In order to have consistent return types and to avoid null-checks everywhere, you cannot return null. If you use the `AbstractIntegerId` base class, the default internal value will be `0`. To check for this a convenient `isDefined()`method is implemented.

```
public function getId(): UserId
{
    return new UserId($this->id);
}
```

### Domain exceptions

[](#domain-exceptions)

Domain exceptions can only be thrown from within the domain. All domain exceptions must implement the `Fusonic\DDDExtensions\Domain\Exception\DomainExcetionInterface`.

### Domain events

[](#domain-events)

Domain objects that extend `Fusonic\DomainDrivenDoctrin\Domain\Model\AggregateRoot` can raise events. Inside the class you can call `$this->raise(...)` with an event that implements `Fusonic\DDDExtensions\Domain\Event\DomainEventInterface`.

All raised domain events will be dispatched when Doctrine `flush` is called. The `Fusonic\DDDExtensions\Doctrine\LifecycleListener\DomainEventLifecycleListener` handles this.

### ORM Mapping

[](#orm-mapping)

You must not use PHP annotations or attributes for defining your ORM mapping. Mapping should be configured outside of the domain. For Doctrine, you can use XML or PHP mapping.

### Value objects as embeddables

[](#value-objects-as-embeddables)

Value object mapping can be done using Doctrine embeddables, but only if it is a one-to-one relation. The advantage of embeddables is that you can use the Doctrine query language to query the fields easily.

### Value objects as JSON

[](#value-objects-as-json)

Another way to map value objects is to define a custom Doctrine type. Extend the `Fusonic\DDDExtensions\Doctrine\Type\ValueObjectType`and implement the `convertToDatabaseValue` and `convertToPHPValue` methods to define the mapping for a value object. The class provides four helper methods for serialization: `serialize`, `deserialize` and `serializeArray`, `deserializeArray` in case you want to store and array of the value objects (one-to-many relation). Example [here](./tests/Doctrine/Types/AddressValueObjectType.php) and [here](./tests/Doctrine/Types/AddressValueObjectCollectionType.php). Inside the database the objects will be stored as `json`.

After implementing the custom type you need to [register it](https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types).

Querying for json data is not possible out-of-the-box in Doctrine, it is however possible using extensions ([example](https://github.com/ScientaNL/DoctrineJsonFunctions)).

###  Health Score

50

—

FairBetter than 96% of packages

Maintenance71

Regular maintenance activity

Popularity27

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~66 days

Recently: every ~117 days

Total

21

Last Release

165d ago

Major Versions

0.0.10 → 1.0.02023-03-07

1.5.0 → 2.0.02024-09-09

2.0.0 → 3.0.02025-03-12

PHP version history (3 changes)0.0.1PHP &gt;=8.0

0.0.8PHP &gt;=8.1

1.2.0PHP &gt;=8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/229567?v=4)[Matthias Burtscher](/maintainers/mburtscher)[@mburtscher](https://github.com/mburtscher)

![](https://avatars.githubusercontent.com/u/338856?v=4)[David Roth](/maintainers/davidroth)[@davidroth](https://github.com/davidroth)

![](https://avatars.githubusercontent.com/u/3588470?v=4)[Arjan Frans](/maintainers/arjanfrans)[@arjanfrans](https://github.com/arjanfrans)

![](https://avatars.githubusercontent.com/u/1465587?v=4)[Michael Zangerle](/maintainers/michaelzangerle)[@michaelzangerle](https://github.com/michaelzangerle)

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

---

Top Contributors

[![arjanfrans](https://avatars.githubusercontent.com/u/3588470?v=4)](https://github.com/arjanfrans "arjanfrans (46 commits)")[![michaelzangerle](https://avatars.githubusercontent.com/u/1465587?v=4)](https://github.com/michaelzangerle "michaelzangerle (23 commits)")[![DominicLuidold](https://avatars.githubusercontent.com/u/22751730?v=4)](https://github.com/DominicLuidold "DominicLuidold (11 commits)")[![mburtscher](https://avatars.githubusercontent.com/u/229567?v=4)](https://github.com/mburtscher "mburtscher (9 commits)")[![janikfu](https://avatars.githubusercontent.com/u/160492061?v=4)](https://github.com/janikfu "janikfu (5 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/fusonic-ddd-extensions/health.svg)

```
[![Health](https://phpackages.com/badges/fusonic-ddd-extensions/health.svg)](https://phpackages.com/packages/fusonic-ddd-extensions)
```

###  Alternatives

[laravel/passport

Laravel Passport provides OAuth2 server support to Laravel.

3.4k85.0M532](/packages/laravel-passport)[nolimits4web/swiper

Most modern mobile touch slider and framework with hardware accelerated transitions

41.8k177.2k1](/packages/nolimits4web-swiper)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k36.7M259](/packages/laravel-dusk)[laravel/prompts

Add beautiful and user-friendly forms to your command-line applications.

712181.8M596](/packages/laravel-prompts)[cakephp/chronos

A simple API extension for DateTime.

1.4k47.7M121](/packages/cakephp-chronos)[laravel/pail

Easily delve into your Laravel application's log files directly from the command line.

91545.3M590](/packages/laravel-pail)

PHPackages © 2026

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