Reputation: 4072
Couldn't get much help from the World Wide Wide Wide Web ...
The situation is:
Is this a normal behaviour?
To work around I am DQLing to empty the oneToMany field target Entity for the mapped by model id and persisting new values
i.e Model: Rule has
/**
* @OneToMany(targetEntity="\Tier", mappedBy="rule", cascade={"persist", "remove"})
* @JoinColumn(name="ruleId", referencedColumnName="ruleId")
* @var Tier[]
*/
public $tiers;
And in the Rule Mapper I am deleting all tiers before calling PERSIST to get UPDATE working:
public function resetTiers($ruleId)
{
$modelClass = "Tier";
$q = $this->doctrineEntityManager->createQuery("Delete from $modelClass m where m.rule =" . $ruleId);
$numDeleted = $q->execute();
return $numDeleted;
}
I don't mind doing this way as long as its OK and not introducing any bad practice.
Thank you for your time.
Upvotes: 0
Views: 113
Reputation: 3321
Please read this bit of Doctrine's documentation.
Doctrine will only check the owning side of an association for changes.
And:
OneToMany is always the inverse side of a bidirectional association.
Although:
You can pick the owning side of a many-to-many association yourself.
So yes, it's normal behavior.
My guess is your ManyToMany
relations are owned by your model (i.e. the Doctrine declaration you put in your property's comment says inversedBy
and not mappedBy
). Which would be why they're automatically updated (as per the doc linked above).
So either you start working on the other side's entities (namely Tier
), or you trick the ORM by updating the other side's entities directly through your Rule
's accessors, probably something like:
public function setTiers($tiers) {
foreach ($this->tiers as $tier) {
$tier->setRule(null);
}
foreach ($tiers as $tier) {
$tier->setRule($this);
}
if (is_array($tiers)) {
//this wrapper is useful if you use syntaxes like
//$someRule->getTiers()->add($someTier); which is usual if you use
//an addTier(Tier $tier) method declared in Rule
$tiers = new \Doctrine\Common\Collections\ArrayCollection($tiers);
}
$this->tiers = $tiers;
}
For the first option, working on other side's entities, just calling $someTier->setRule($someRule)
will auto-update* $someRule
's $tiers
.
*: auto-update should happen 1/ when you flush your mods and 2/ maybe you'll need to refresh the $someRule
object (I mean the EM's refresh
method).
All of this is "my guess", anyone feel free to correct, and OP feel free to give some feedback about how it went if you try this! ;)
Here is some more doc about updating related entities, especially at the bottom of the page, section 6.14.1.
Hope this helps!
Upvotes: 1