PHPackages                             alexandrebulete/ddd-doctrine-bridge - 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. alexandrebulete/ddd-doctrine-bridge

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

alexandrebulete/ddd-doctrine-bridge
===================================

Doctrine ORM bridge for DDD Foundation - Pure PHP, no framework dependency

1.1.4(1mo ago)119↓60.9%1MITPHPPHP ^8.2

Since Dec 27Pushed 1mo agoCompare

[ Source](https://github.com/AlexandreBulete/ddd-doctrine-bridge)[ Packagist](https://packagist.org/packages/alexandrebulete/ddd-doctrine-bridge)[ RSS](/packages/alexandrebulete-ddd-doctrine-bridge/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (8)Versions (7)Used By (1)

DDD Doctrine Bridge
===================

[](#ddd-doctrine-bridge)

Doctrine ORM bridge for DDD Foundation. This package provides repository and paginator implementations using Doctrine, plus custom DBAL types for Value Objects.

**Pure PHP** - No framework dependency. Use with any PHP framework.

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

[](#installation)

```
composer require alexandrebulete/ddd-doctrine-bridge
```

For Symfony integration, also install:

```
composer require alexandrebulete/ddd-doctrine-bundle
```

Structure
---------

[](#structure)

```
src/
├── DoctrineRepository.php
├── DoctrinePaginator.php
├── DispatchesDomainEvents.php
├── Capability/
│   ├── AsReadable.php          # CanFindById + CanFindAll
│   ├── AsMutable.php           # CanPersist + CanRemove + DispatchesDomainEvents
│   └── AsCrudable.php          # AsReadable + AsMutable
├── Operation/
│   ├── CanPersist.php          # persistAndFlush()
│   ├── CanRemove.php           # removeAndFlush()
│   ├── CanFindById.php         # findEntityById()
│   └── CanFindAll.php          # findAllEntities()
├── Enum/
│   └── WhenDispatchDomainEventsEnum.php
└── Type/
    ├── BaseType.php
    ├── GuidType.php
    ├── TextType.php
    ├── VarcharType.php
    └── Convertor/
        ├── AsIdentifierConvertor.php
        └── AsStringConvertor.php

```

Repository Traits
-----------------

[](#repository-traits)

Granular traits to compose your repositories with only the capabilities you need.

### Capability Traits (High-level)

[](#capability-traits-high-level)

TraitIncludesUse case`AsReadable`CanFindById, CanFindAllRead-only repositories`AsMutable`CanPersist, CanRemove, DispatchesDomainEventsWrite-only repositories`AsCrudable`AsReadable, AsMutableFull CRUD repositories### Operation Traits (Atomic)

[](#operation-traits-atomic)

TraitMethodDescription`CanPersist``persistAndFlush()`Persist and flush entity`CanRemove``removeAndFlush()`Remove and flush entity`CanFindById``findEntityById()`Find entity by ID`CanFindAll``findAllEntities()`Find all entities### Usage Examples

[](#usage-examples)

#### Full CRUD Repository

[](#full-crud-repository)

```
use AlexandreBulete\DddDoctrineBridge\DoctrineRepository;
use AlexandreBulete\DddDoctrineBridge\Capability\AsCrudable;
use AlexandreBulete\DddFoundation\Application\Event\EventDispatcherInterface;

class DoctrinePostRepository extends DoctrineRepository implements PostRepositoryInterface
{
    use AsCrudable;

    public function __construct(
        EntityManagerInterface $em,
        private readonly EventDispatcherInterface $eventDispatcher,
    ) {
        parent::__construct($em, Post::class, 'post');
    }

    public function save(Post $post): void
    {
        $this->persistAndFlush(
            entity: $post,
            dispatchEvents: true,
            whenDispatchEvents: WhenDispatchDomainEventsEnum::AFTER,
        );
    }

    public function delete(Post $post): void
    {
        $this->removeAndFlush($post);
    }

    public function findById(IdentifierVO $id): ?Post
    {
        return $this->findEntityById(Post::class, $id->toRfc4122());
    }

    public function findAll(): array
    {
        return $this->findAllEntities();
    }
}
```

#### Read-Only Repository

[](#read-only-repository)

```
use AlexandreBulete\DddDoctrineBridge\DoctrineRepository;
use AlexandreBulete\DddDoctrineBridge\Capability\AsReadable;

class DoctrineCountryRepository extends DoctrineRepository
{
    use AsReadable;

    public function __construct(EntityManagerInterface $em)
    {
        parent::__construct($em, Country::class, 'country');
    }

    public function findById(IdentifierVO $id): ?Country
    {
        return $this->findEntityById(Country::class, $id->value());
    }

    public function findAll(): array
    {
        return $this->findAllEntities();
    }
}
```

#### Custom Mix (Persist without Delete)

[](#custom-mix-persist-without-delete)

```
use AlexandreBulete\DddDoctrineBridge\DoctrineRepository;
use AlexandreBulete\DddDoctrineBridge\Capability\AsReadable;
use AlexandreBulete\DddDoctrineBridge\Operation\CanPersist;
use AlexandreBulete\DddDoctrineBridge\DispatchesDomainEvents;

class DoctrineAuditLogRepository extends DoctrineRepository
{
    use AsReadable;
    use CanPersist;
    use DispatchesDomainEvents;

    // Can read and create, but NOT delete
}
```

Domain Events
-------------

[](#domain-events)

Dispatch domain events from your aggregates after persistence.

### When to Dispatch

[](#when-to-dispatch)

```
use AlexandreBulete\DddDoctrineBridge\Enum\WhenDispatchDomainEventsEnum;

// Dispatch AFTER flush (recommended - ensures transaction committed)
$this->persistAndFlush($entity, dispatchEvents: true, whenDispatchEvents: WhenDispatchDomainEventsEnum::AFTER);

// Dispatch BEFORE flush (rare - event dispatched even if flush fails)
$this->persistAndFlush($entity, dispatchEvents: true, whenDispatchEvents: WhenDispatchDomainEventsEnum::BEFORE);
```

### Requirements

[](#requirements)

Your entity must use the `RecordsEvents` trait from `ddd-foundation`:

```
use AlexandreBulete\DddFoundation\Domain\Model\RecordsEvents;

class Post
{
    use RecordsEvents;

    public function publish(): void
    {
        $this->status = 'published';
        $this->recordEvent(new PostPublished($this->id));
    }
}
```

Custom Doctrine Types
---------------------

[](#custom-doctrine-types)

Create custom Doctrine types for your Value Objects:

```
use AlexandreBulete\DddDoctrineBridge\Type\GuidType;
use App\Post\Domain\ValueObject\PostId;

class PostIdType extends GuidType
{
    protected string $name = 'post_id';
    protected string $voClass = PostId::class;
}
```

### Available Base Types

[](#available-base-types)

- **GuidType**: For UUID/ULID identifier value objects
- **VarcharType**: For string value objects (VARCHAR)
- **TextType**: For string value objects (TEXT/CLOB)

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 78.9% 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 ~37 days

Recently: every ~43 days

Total

6

Last Release

47d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/15733a17c9dd08fc7def3be016f324453d4f0de828438858d13f63e7c3388353?d=identicon)[Alexandre Buleté](/maintainers/Alexandre%20Bulet%C3%A9)

---

Top Contributors

[![AlexandreBulete](https://avatars.githubusercontent.com/u/40428152?v=4)](https://github.com/AlexandreBulete "AlexandreBulete (15 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (4 commits)")

### Embed Badge

![Health badge](/badges/alexandrebulete-ddd-doctrine-bridge/health.svg)

```
[![Health](https://phpackages.com/badges/alexandrebulete-ddd-doctrine-bridge/health.svg)](https://phpackages.com/packages/alexandrebulete-ddd-doctrine-bridge)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k6.0M777](/packages/sylius-sylius)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k18.3M430](/packages/easycorp-easyadmin-bundle)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M236](/packages/sulu-sulu)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1617.3k16](/packages/2lenet-crudit-bundle)[neos/neos-development-collection

Neos packages in a joined repository for pull requests.

267104.3k1](/packages/neos-neos-development-collection)[rcsofttech/audit-trail-bundle

Enterprise-grade, high-performance Symfony audit trail bundle. Automatically track Doctrine entity changes with split-phase architecture, multiple transports (HTTP, Queue, Doctrine), and sensitive data masking.

12017.1k](/packages/rcsofttech-audit-trail-bundle)

PHPackages © 2026

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