Generate setters for Datetime and fixed point decimal that check if the value has *really* changed #1052
Description
Summary
maker bundle should generate sensible setters to avoid people falling in a common pitfall
Context
As of January 2022, doctrine has a 'logical but confusing' behaviour
doctrine/orm#5542
doctrine/orm#1924
it's because of this line https://github.com/doctrine/orm/blob/bd949312016be418c36603d89951b9641f79ffdb/lib/Doctrine/ORM/UnitOfWork.php#L660
that does a ===
comparison, so for an object, it compares the reference and not the value
so admitting you have an entity Employee with arrival date 2021-01-01
and firstname robert
doing
$employee->setFirstname('robert');
$em->persist($employee);
$em->flush()
-> it does not generate a SQL request because the value was robert and it hasn't changed
but going
$employee->setArrivalDate(new \Datetime('2021-01-01'));
$em->persist($employee);
$em->flush()
-> it generates a new request because this is a new object though the date hasn't changed
a workaround waiting an official solution from doctrine/orm#5542
is to do a check manually in the setter (so we do it once and for all) and not change if "equal" in a logical (same datetime/same amount)
currently at least decimal and datetime fields are concerned (datetime because a new reference is created, decimal because a strict string comparison is not sufficient , i.e '0' and '0.0' will generate a UPDATE though they're actually a real value )
Proposed solutions
- simply add a warning comment in the setter
public function setLinkedAt(\DateTimeInterface $linkedAt): self
{
// warning, this may generate unecessary update: see *link*
$this->linkedAt = $linkedAt;
return $this;
}
2. we could more opinionated (like we are for some other types that generates more complex setters already)
we could generate
public function setLinkedAt(\DateTimeInterface $linkedAt): self
{
// we do this because : *link explaining the issue*
if ($this->linkedAt != $linkedAt) {
$this->linkedAt = $linkedAt;
}
return $this;
}