Doctrine 2 entities relationships: cascade merging - symfony

I manage complex entities, with multiple and different relationships with other entities, which themselves are linked to multiple other entities sometime.
I am making an edit form, and would like to avoid having to code manually different Doctrine 2 queries to udpate every entity linked to the modified entity.
Is it possible to cascade merge entities in Doctrine 2 ? By that, I mean modifying an entity and its linked entities (oneToMany, ManyToMany... relationships) and then applying the changes to the entity and the linked entities in cascade.
If not, what is the 'clean' way to apply modifications to all the concerned entities ? Does it need to be manually done, by calling merge or update on every entity ?

It seems you are working on Symfony (correct me if I'm wrong).
On symfony forms, when you are working with underlying objects, you sometimes need to put 'by_reference' option to 'false' in order to correctly handle the underlying modified objects.
See that : https://symfony.com/doc/current/reference/forms/types/form.html#by-reference
Hope it helps.

Most probably the problem has nothing to do with symfony but more with your doctrine relationships. You should check your associations as changes made only to the inverse side of an association are ignored by doctrine. Refer to the documentation.

Related

Symfony : relation with multiple entiy types

I am building an application where a User can have relation with multiple kind of entities : skills, tools, styles.
Those relations contain extra info like a rating.
My user entity will have three different attributes (skills, tools, styles) but I would like to use the same intermediary table for each of those relations.
I plan to build something like that :
User
Name
...
Tools
Skills
Style
UserRates
User id
Tool/style/skill id
Relation type ("tool", "style", "skill")
Rate
Tools
Name
...
Skills
Name
...
Styles
Name
...
Another similar scenario would be to build a system to rate anything (blog posts, events, images, ...).
I can't imagine a system where you have to rebuild the relation for each new notable entity.
My questions are:
Is this kind of relation is doable in SF2?
Do you know any good example / article?
How would you do it ? I guess I need a custom repository and custom setters/getters ?
Tools
Entities are handled by an ORM. I'm guessing you're using Doctrine as it comes standard with Symfony2+.
How to do relationships
Relations are done with Doctrine mappings which you can find here on their documentation website.
Note: the annotations in the doctrine documentation do not have the #ORM/ prefix, which Entities which are part of Symfony2 require (look at "use" statments to see why). So you'll have to add them yourself.
PS: Unless you have very good reason to relate all those entities via one intermediary table, don't do it.
I should also note that when dealing with an ORM you should not be thinking about tables, but about objects. Doctrine will generate an intermidiary table for ManyToMany relationsips automatically.
You'll only need to create one yourself (and thus have ManyToOne IntermidiaryEntity OneToMany relationships) when the relation has to carry extra information.
As someone has already suggested, I suggest reading the relevant chapter in Symfony2's amazing book.

Is this a good practice to use one entity in two different entities in a oneToMany Relationship?

I'm actually having 3 entities: Bounty, Document, and Comment. When i first made the Comment entity, it was to serve the document Commentary purpose. Later i have added a newer entity called "Bounty", and i was expecting to use the same Comment entity that i was already using in the Document entity.
I wish to avoid having one DocumentComment entity, and another BountyComment entity.
Is having one Comment Entity is a good way to procede, or should i rather separate them in two different entities ?
If grouping entites is a good practice, how can i make them fit when there can be duplicate entry ?
If both identities have the exact same structure and this fact is never going to change, you could group them together. However, every comment belongs to some other entity, so if it belongs to a Document, it needs a property "document". If it belongs to a Bounty, it needs a property "bounty". So the two are not the same.
If you are using ORM (e.g Doctrine), you can use a shared base class and extend from it. Doctrine will create seperate tables for each type, but you can share functionality between the entity classes. See http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html

Doctrine - Creating and mapping an entity based on a SQL query?

Would it be possible to create a similar entity based on another one? For example, what if I'd like to have user specific tables that are based on one entity. Without any ORM I would just create the same table with a different prefix and do the queries on the table with the specific prefix.
Not sure how to tackle the problem with Symfony 2.5 and Doctrine and I just can't find a concrete example anywhere around, but seems like the solution might be around the Doctrine Event Manager and the Load ClassMetadata event. I just can't make sense out of the documentation.
Without exactly knowing how your schema looks or what you're trying to achieve, it's hard to give a precise answer. But let's try:
If you have two entities which share a common set of properties, but differ in others, you basically do the typical OOP inheritance thing, you create an abstract parent class with the common stuff, and two children with their specific properties.
In Doctrine, there are different inheritance strageties. Read about them at http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
Each of them has their pros and cons. Basically, you can select if you want everything to be in one or in two tables. Set up a test case and check what works better for you.
Note: The class properties in an abstract superclass (no matter which strategy) must always be private.

Associated entity being persisted but no cascade option setted

In doctrine documentation I found: "By default, no operations are cascaded." (here http://bit.ly/1frPyLH)
But still one of my database entities is persisting it's associated objects, besides the fact that it has no cascade option in the association.
How can I prevent it from persisting the associated entities ?
It is true and the documentation is still not wrong. =P
Without going deeper on your problem, you need to be aware that by default Doctrine applies a concept called "persistence by reachability". This means that if you are creating a new entity and one of your associations is already managed by UnitOfWork (already known by Doctrine), it will "cascade" the operation.
The problem here is how you read about cascading. In reality, it's not the cascading factor that is updating the associated entity, but it's because it's already managed by Doctrine.
To solve this "problem", you need to modify the way you want Doctrine to deal with your entities by altering the Change Tracking Policy.
I hope this gives you enough information to solve your issue.

Using Relationships with Multiple Entity Managers

I am wondering if it is possible to create a relationship between two entities that reside in separate databases.
For example if we took the solution found here http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html and created a one to many relationship with Users in the customer database to Posts in the default database.
Is this something that is supported by Symfony2 and Doctrine?
Using different object managers (entity managers) doesn't allow the object graphs to intersect. That case is too complex and isn't managed by Doctrine ORM.
If you need such a case, keep the object graphs disconnected by saving the identifiers of the related objects (old style) instead of a reference to them, then manually get the objects through services. You can find a fairly good example of how this would work in an example of connection between Doctrine2 ORM and Doctrine2 MongoDB ODM. Alternatively, you could also use a #PostLoad event listener that populates data in your entities by creating the link through the repositories I've linked in the example. Same for #PostPersist (which should instead extract the identifiers for the related objects), but beware that this technique can become really messy.
Also, if your RDBMS supports cross-database operations on a single host, you can just use a single EntityManager and reference the other table with #ORM\Table(name="schemaname.tablename").

Resources