I have a modeling issue with Symfony2/Doctrine2. I am currently trying to pass a whole web site from a former PHP framework to Symfony2, and there's a conception in the former framework which I like but which I can't manage to modelize with Symfony and Doctrine.
Here is my issue : with the former framework, it's possible to link an object of a class A to any other object of any other class (B,C,D...). To do this, the class A has an attribute model_id to know which class the object is linked to (it corresponds to a unique id defined in a configuration file for each class), and an attribute record_id which is the external id of the linked object. This way, for example, it's possible to have a class Comment and have a comment about any object (a blog post, a user, etc.).
As these generic links seem impossible to modelize with Doctrine relationships (ManyToOne etc.), I thought about having - like in the former framework - a sort of global method, or a method for each class, called for example getItem, which looks at the attributes model_id and record_id and then return the right object.
But again I had problems :
I can't define this method in the Entity directly because I shouldn't have access to the database in the Entity class.
If I define it once in a global service, or n times for each class in a repository - which is possible because this time I have access to the database - I will be able to call the method everywhere but in the Entity code. And it makes the implementation pretty ugly because it means that in my previous example all the methods of the Entity which need to have access to the Comments must be moved from the Entity to the Repository. And finally I will have pretty much all my object methods in the Repository rather than in the Entity directly.
Do you have any idea about how I could have a system like this which allows to link generically an object to any other object and then recover easily the linked object just like it was a "usual" Doctrine relationship ?
Thank you very much in advance for your help.
The thing is your solution means we know in advance that the object A is going to be linked to an object B, C, etc. However, what I wanted to implement is a solution where we don't know in advance what are going to be the links and we have the possibility to create a new link between the object A and an object of a newly created class Z without changing anything in the classes A and Z. This way, if I take my previous example, you can properly have a Comment on any Object, without making straight relationships between the class Comment and the other classes.
And I think I found the solution to this problem:
What I've done is implementing a Listener, with the event postLoad which triggers each time an entity is loaded from Doctrine. On the other hand, my entities have for example an attribute $item which is the linked item for which we don't know the class yet. In the postLoad event, we look in the database thanks to model_id and record_id what is the class of the linked item and return the object itself, and then we fill the $item attribute before the entity is returned by Doctrine. This way, each time we get an entity from Doctrine, the "fake" link between the entity and the item is built by the automatic event, and this works for every entity. With the same principle, we can update the link with a postUpdate event which triggers each time we update the entity. It will update manually the "fake" link in the database.
For more information, I recommend to read these pages :
The way I have implemented something similar to this is fairly easy, though not exactly straight forward:
You would create a new class, I'll propose a name like:
In that you would make your links to other objects:
This lets you associate it with multiple other ones. You'd only ever use one of the remote ids at a time, but it lets you use it across objects and also take advantage of the orm.
If you wanted to not worry so much about the initial object->comment_thread setup, then I would recommend perhaps just: