Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce coupling in entities

I'm looking for an appropriate way to reduce coupling in a messaging bundle I'm writing for the Symfony2 framework, so that I can easily use it between applications.

Each instance of the Message entity should have a sender and a recipient, instanceof Symfony\Component\Security\Core\User\UserInterface, which I can require just fine in the setters for the properties. However, in setting up the ORM relationships, it seems that I have to specifically set a targetEntity (Foo\BarBundle\Entity\User, for example), which means that all further uses of the Message entity in different applications will either require a code change, or shoehorn them into using a User entity, which doesn't seem to me to be in a messaging bundle's scope to require.

Any suggestions/best practices on how I can reduce coupling in this instance?

EDIT: I tried setting a global parameter with an extension and using that in the annotations, something like @ORM\ManyToOne(targetEntity="%my.entity%"), but it seems that the annotation parser doesn't convert parameters, because the string was interpreted as a literal, which failed, of course.

like image 670
Derek Stobbe Avatar asked May 23 '11 23:05

Derek Stobbe


2 Answers

The solution I finally settled on was to create a MessengerIdentity, stored in the database, that takes an object and stores its class name and identifier. Then I used a LifecycleEvent to load a reference to the entity stored in MessengerIdentity, so that something like $messenger->getSender()->getUsername is still possible.

You can see my implementation on github (in particular, the entities and the Doctrine event listener)... you can also see the discussion from the doctrine2 usergroup here.

EDIT: After further deliberation, I decided that I didn't like the implementation I talk about above (for one thing, I was essentially copy-pasting the code into other projects, which felt very cluttered and in violation of DRY), and so I refactored my code so that the Message entity is an abstract mapped superclass, with abstract methods that the business logic will need, referencing the sender and recipient.

It's now up to the end developer to create the final implementation of the Message entity, and the base class doesn't even touch the implementations for sender and recipient, which achieved my desired result of reducing dependence of the bundle on a particular user class.

like image 160
Derek Stobbe Avatar answered Sep 28 '22 20:09

Derek Stobbe


You could create a Model object with all the business logic in and then create an Entity which extends the model but adds your entity manager code and doctrine annotations to it. This is how FOSUserBundle works.

like image 33
jmoz Avatar answered Sep 28 '22 19:09

jmoz