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(2d ago)14↓86.7%1MITPHPPHP ^8.2

Since Dec 27Pushed 4mo 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 today

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

40

↑

FairBetter than 86% of packages

Maintenance85

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 82.4% 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

2d 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 (14 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (3 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

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M388](/packages/easycorp-easyadmin-bundle)[sylius/sylius

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

8.5k5.9M738](/packages/sylius-sylius)[sulu/sulu

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

1.3k1.4M203](/packages/sulu-sulu)[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.

1189.8k](/packages/rcsofttech-audit-trail-bundle)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k14](/packages/2lenet-crudit-bundle)[ahmed-bhs/doctrine-doctor

Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler. Unlike static linters, it analyzes actual query execution at runtime to detect performance bottlenecks, security vulnerabilities, and best practice violations during development with real execution context and data.

9410.8k](/packages/ahmed-bhs-doctrine-doctor)

PHPackages © 2026

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