Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ddd Doctrine Bridge Laravel Package

alexandrebulete/ddd-doctrine-bridge

View on GitHub
Deep Wiki
Context7

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

composer require alexandrebulete/ddd-doctrine-bridge

For Symfony integration, also install:

composer require alexandrebulete/ddd-doctrine-bundle

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

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

Capability Traits (High-level)

Trait Includes Use case
AsReadable CanFindById, CanFindAll Read-only repositories
AsMutable CanPersist, CanRemove, DispatchesDomainEvents Write-only repositories
AsCrudable AsReadable, AsMutable Full CRUD repositories

Operation Traits (Atomic)

Trait Method Description
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

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

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)

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

Dispatch domain events from your aggregates after persistence.

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

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

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

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

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity