I managed to make a many to many relationship work correctly using mysql, doctrine 2 and symfony 3.4.
When a new element A that contains 0 to m element Bs is inserted, the B elements that already have the same content are reused, instead of creating new ones.
This is not the default doctrine 2 behaviour in a ManyToMany context with cascade={"persist", "remove"}
.
The relationship uses an intermediate / join table, that contains id of table A and id of table B.
What I did is after deserializing the element A that contains m B elements, I check for each element B if a similar already exist in database.
If yes, I reuse it, if not I let doctrine cascade persist / insert new elements B.
Pseudocode, inside element A repository.
function useExistingDatabaseElementsBForNewElementA($elementA) {
$elementsBs = $elementA->getElementsBs()
// use existing elements B if available in database
foreach ($elementsBs as $B) {
/** @var B $matchingB*/
$matchingB= $this->elementBRepository->findOneBy(['data' => $B->getData()]);
if ($matchingB) {
$elementA->removeElementB($B);
$elementA->addElementB($matchingB);
}
}
}
I do this in the element A repository, by calling the findOne method of the element B repository and checking the result.
Is this is an acceptable / correct design choice / implementation.
How can it be better, for example using doctrine 2 configuration / annotations instead of my custom method in the element A repository ?
Could it be cleaner to implement it elsewhere or another way ?