mik
mik

Reputation: 1575

symfony domain event

I'm trying to implement Domain Driven Design in my Symfony2 project and experience some problems. After reading some articles on Domain Models I found, that

Luckily, Symfony provides Events, but here is a problem - I can't raise event from my entity. Symfony documentation suggects to use DI to inject the dispatcher into the class, that raises Event

http://symfony.com/doc/current/book/internals.html#passing-along-the-event-dispatcher-object

But Symfony Entities are newable, not injectable. Right now I can see two ways:

1) Provide Event Dispather to Entity like this

class FooEntity
{
    protected $dispatcher = null;

    public function setEventDispatcher(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
}

2) Raise Events from the service(not from the Entity).

None of this options look pretty, because it seems to me that they break Domain Model ideology. Can you point me in the right direction, please.

Upvotes: 6

Views: 2546

Answers (2)

renoirb
renoirb

Reputation: 559

The idea of this here is to give paths to attain the DDD paradygm.

I do not want to shadow over @magnusnordlander answer, I will apply what he says.

Here is some of observations on the matter:

I think that the Entity itself should not have everything. It is sure not what the DDD people would say anyway. The [Doctrine2] Entity should only take care of the relationships (an entity with different variation too <= This is actually a thing that I was stuck for a while) and the aggregate root.

The Doctrine entity should only know about how to work with itself.

But, to Get Data or work with it, there is other stuff that you can use:

Repository

Is the thing that provides helpers to get your more sophisticated finders than what a quick findBy(array('id'=>$idvalue)) would do (and that the Entity/Assocation/Annotation cannot cover) and is indeed a great thing to have handy.

I personally tried to build all queries, and realized the EntityManager is already very good, out of the box. In most case, to my opinion: If you can /not/ use query or query builder, the better.

Business logic in all that...

Last thing on note, what you would be searching for must be to basically thin the Controller.

FooManager (for example) is where (if I am not mistaken) the business logic go.

I found a goldmine of information on that matter on this blog that covers:

If you have any ideas, to augument, I set this answer as a Community Wiki

Upvotes: 2

Magnus Nordlander
Magnus Nordlander

Reputation: 373

By Symfony entities, do you mean Doctrine 2 entities? If so, you can set services on both new objects and old objects that are loaded from the database in the following manner:

Prototype scoped service

Services in the prototype scope are always recreated when you get them. Instead of doing new FooEntity you would do $container->get('foo_entity').

In the YAML syntax you would define the service as follows:

foo_entity:
  class: FooEntity
  calls: 
    - [setEventDispatcher, [@event_dispatcher]]
  scope: prototype

This will take care of new entities. For existing entities you need a...

Post load event listener

Create an event listener, in the manner described here:

http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html

Have the listener listen for the postLoad-event. Inject the event dispatcher into the listener service, and use the listener service to set the event dispatcher on the entity.

Bear in mind that the listener service will fire after loading any entity, not just the FooEntity, so you'll need to do a type check.

Upvotes: 2

Related Questions