Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement DDD with Doctrine2 within a Symfony2 project?

Well I'm trying to introduce myself to DDD, I'm very new to it and some concepts are still unclear.

Here is what I understood so far:

  • The domain is basically about data
  • The persistence layer is not tied to the domain, but business logic transaction may be.

When using Doctrine2, we use either EntityRepository or a CustomEntityRepository implementation.

In DDD, the Repository pattern seems a bit different, I've looked at .NET & Java examples as well as messages from the DDD mailing list, and people tends to accord that the repository should returns QueryObject, in Doctrine2, I project to return QueryBuilder instance from my repository.

Therefore to hide the complexity of working with QueryBuilder then a Query then an Hydrated result set, I implemented another service layer which I called Manager.

Here is how my domain looks like:

src/Domain/
├── Entity
│   ├── AbstractComment.php
│   ├── Comment.php
├── Manager
│   ├── CommentManager.php
└── Repository
    └── CommentRepository.php

The Entity folder is just about pure POPO.

The CommentRepository looks like this:

<?php
namespace Acme\Domain\Repository;

use Doctrine\Common\Collections\Criteria;

class CommentRepository
{
    private $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    /**
     * @param $id
     *
     * @return \Doctrine\ORM\QueryBuilder
     */
    public function findOneById($id)
    {
        $qb = $this->getEntityManager()
            ->getRepository('Acme:Domain\Entity\Comment')
                ->createQueryBuilder('c');

        $criteria = new Criteria();

        $criteria->andWhere(
            $criteria->expr()->eq('c.id', ':id')
        );

        $qb->addCriteria($criteria);

        $qb->setParameter('id', $id);

        return $qb;
    }
}

And the CommentManager:

<?php

namespace Acme\Domain\Manager;

class CommentManager
{
    protected $repository;

    public function __construct(CommentRepository $repository)
    {
        $this->repository = $repository;
    }

    public function findOneById($id)
    {
        return $this->repository->findOneById($id)->getQuery()->getOneOrNullResult();
    }
}
  1. Is it the correct approach for managing "entities"?
  2. Following such pattern, where do I have to handle the persistence?

I mean, if I'm right, the repository is basically like a collection, therefore it should provide add(Entity $e) and remove(Entity $e) methods, but where do I actually persist the entity?

Is it safe to do it inside the add() & remove() methods? Is it better to add a save() method to handle updates?

Thank you for your time.

like image 618
Trent Avatar asked Feb 17 '23 13:02

Trent


1 Answers

I started a series about DDD with Symfony2 that should answer your questions: http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/.

I mean, if I'm right, the repository is basically like a collection

Yes.

therefore it should provide add(Entity $e) and remove(Entity $e) methods

Yes.

but where do I actually persist the entity?

In this repository. However, this is probably not a Doctrine repository. Doctrine uses Entity/Repository terms, but they don't have the same meaning in DDD.

like image 181
William Durand Avatar answered Mar 05 '23 02:03

William Durand