Domain-Driven Design Repositories with Doctrine ORM and ODM in Symfony

0 Flares Twitter 0 Facebook 0 LinkedIn 0 0 Flares ×

Welcome to my first Domain-Driven Design in PHP post.

DDD in PHP

The following code is inspired by the Domain-Driven Design in PHP book written by Carlos Buenosvinos (@carlosbuenosvinos) and Keyvan Akbary (@keyvanakbary):

Value Objects

My examples code include Value Objects for the identifiers of Aggregate Roots (AR) For now they will be created manually. Later we will see how to use custom Doctrine DBAL types to persist them.

Interface

Doctrine Repository

ORM

ODM

The ODM implementation (e.g. MongoDB) looks very similar:

Service

Mapping

I recommend to use XML mapping for your Domain Models. This way your class remains POPO and does not mix ”’infrastructure”’ with ”’domain”’ concerns.

Feel free to join the discussion about this topic on GitHub:

Document

Here is an ODM Document example:

Entity

For those who still like to use annotations here is an example Entity:

Usage

Handler

Controller

Naming Conventions

Feel free to join the discussion about naming repositories and other best practices on GitHub.

 

webdevilopers

  • Yonn Aden Hugo

    I was reading through your posts on GitHub and maybe came to a simple solution for you.. (but maybe I didn’t understand all of the problem, correct me if I’m wrong !)
    And the solution is: why not letting dependency injection do its job ? Let me explain:
    1 – Declare a ‘FooRepository’ interface
    2 – Define two classes ‘FooMySQLRepository’ and ‘FooMongoDBRepository’
    3 – Use dependency injection with autowiring enabled everywhere in your app (in your controllers, managers…) and call for interfaces in constructors, not implementations
    4 – Tell Symfony’s dependency injection which one to inject (from those which implement corresponding Interface) in your controllers/managers’ constructors (http://symfony.com/doc/current/components/dependency_injection/autowiring.html#working-with-interfaces)
    5 – Same thing is possible with Entities using Doctrine’s resolve_target_entities’ option in conf (http://symfony.com/doc/current/doctrine/resolve_target_entity.html)
    I can assemble a quick example if you want
    Have a nice day
    PS: this solution also have the advantage of letting DevOps/DBAs choose the type of storage on their own if you let them only edit the config file (and if you keep the implementations in sync).

    • Actually there is no problem! 🙂 I just showed both implementations for ORM and ODM.

      The main difference to your attempt is that Domain and Infrastructure Layer are decoupled.
      The Interface belongs to the Domain Model, the implementation to the Infrastructure.
      You could even move the mappings to the Infrastructure Layer.

      So you don’t need Symfony at all – just for the DI. I prefer manually wiring instead of “magic”. Write once – use forever.