Open Firehed opened 2 years ago
I have experienced exactly same bug on 2.13.1
.
In my case error showed when I changed Doctrine\ORM\Mapping\GeneratedValue
strategy of my id property from default auto increment to UUID generated using Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator
.
After some trying I have found a solution that works for me
In entity I had
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\Column(type: 'uuid')]
private readonly string $id;
When trying to access any property (other than ID) I got mentioned error
Changing column type from uuid
to string
solved this for me.
My assumption is that this error is caused by handling of a UUID
type field in Postgres.
Maybe someone smarter will be able to confirm this.
Ran into the same problem, but with DBAL custom type (private readonly SomeId $id
) , not autogenerated, id. This was for a OneToOne
association. My fix was to replace readonly
with a @psalm-immutable
annotation on the id
property temporarily.
Ran into the same problem with $id being a custom type build around a Symfony uuid. The cause seems to be the strict comparison in ReflectionReadonlyProperty.php:45
if (parent::getValue($objectOrValue) !== $value) {
throw new LogicException(sprintf('Attempting to change readonly property %s::$%s.', $this->class, $this->name));
}
When I inspect the values in xdebug console, both represent the same uuid, but having different object id's fails the comparison:
> parent::getValue($objectOrValue)
< App\Domain\Tag\TagGroupId::__set_state(array(
'uuid' =>
Symfony\Component\Uid\UuidV3::__set_state(array(
'uid' => '3a705d0d-54e1-37b8-bd58-b4a188fa126a',
)),
))
> $value
< App\Domain\Tag\TagGroupId::__set_state(array(
'uuid' =>
Symfony\Component\Uid\UuidV3::__set_state(array(
'uid' => '3a705d0d-54e1-37b8-bd58-b4a188fa126a',
)),
))
> spl_object_id(parent::getValue($objectOrValue))
< 4875
> spl_object_id($value)
< 4737
I encountered the issue today with a readonly classs around an int / IDENTITY id column:
#[ORM\Entity]
readonly class Sample
{
#[ORM\Id, ORM\GeneratedValue(strategy: 'IDENTITY')]
#[ORM\Column()]
private int $id;
//...
}
I have the same issue in the following situation
class Dog
{
private function __construct(
private readonly Uuid $id
) {
// ...
}
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="App\Entity\Dog"
table="xxx"
repository-class="xxx">
<id name="id" type="uuid" column="id"/>
<field name="createdAt" column="created_at" type="datetime_immutable" />
</entity>
</doctrine-mapping>
The error occurs in a frontend situation where we are fetching DogOwners, which has a many-to-one to Dog
<many-to-one field="Dog" target-entity="App\Entity\Dog" inversed-by="userDogs">
<join-column name="dog_id" referenced-column-name="id" />
</many-to-one>
Having the same issue on:
doctrine/orm: 2.18.0
doctrine/dbal: 3.8.1
User entity:
final class User extends AggregateRoot implements EntityInterface
{
private readonly EntityId $id;
...
public function __construct(
private Email $email,
private HashedPassword $password,
) {
$this->id = new EntityId();
}
...
}
ORM definition:
...
<entity name="App\Xyz\Domain\Entity\User" table="`user`" repository-class="App\Xyz\Infrastructure\Doctrine\Repository\UserRepository">
<id name="id" type="entity_id">
<generator strategy="NONE"/>
</id>
<field name="email" type="email" unique="true"/>
<field name="password" type="hashed_password"/>
...
</entity
...
Getting an error after POST operation (insert):
request.CRITICAL: Uncaught PHP Exception LogicException: "Attempting to change readonly property App\Xyz\Domain\Entity\User::$id." at ReflectionReadonlyProperty.php line 46 {"exception":"[object] (LogicException(code: 0): Attempting to change readonly property App\Xyz\Domain\Entity\User::$id. at /app/vendor/doctrine/orm/src/Mapping/ReflectionReadonlyProperty.php:46)"} []
Me too
Any updates about this issue?
I debugged to the same point as @cl1ck did: There are two Uuid objects with the same content, but being different objects.
In my case it is an ID with Symfony Uuid
type which is set inside the constructor. Seems as the object is hydrated twice from the same Uuid
coming from the database. In my case it belongs to a EXTRA_LAZY
fetched ManyToOne
related Entity of the Entity being shown on that route. Maybe when generating the proxy object, the related Uuid-identified Entity gets only its ID hydrated and when I access its data, the whole object gets hydrated and with it its ID again and those two Uuid-objects have the dame value, but are not the same object. And thus, the if (parent::getValue($objectOrValue) !== $value)
check inside ReflectionReadonlyProperty.php
fails and we see that error. Changing the relation fetch mode to EAGER
also fails btw., so that is not the cause. Anyhow, that !==
seems to be too strict.
I have some other Entities with a readonly Uuid
-based ID and do not see the error there, the only difference ist that none of those are ManyToOne
related in other Entities and all other Entities that are ManyToOne
related have integer based IDs or non-readonly Uuid based IDs.
Hello, I face the same issue. Has somebody found a solution nor a workaround?
This seems a duplicate of #9505
Hello, I face the same issue. Has somebody found a solution nor a workaround?
I suggest using this option until the problem is resolved. I think this is the most correct option at the moment, so that it can be quickly corrected with future updates:
/**
* @readonly impossible to specify "readonly" attribute natively due
* to a Doctrine feature/bug https://github.com/doctrine/orm/issues/9863
*/
#[ORM\Id]
#[ORM\Column(name: 'id', type: ExampleId::class)]
public ExampleId $id;
Bug Report
Summary
When initializing a proxy by accessing a non-loaded property, if the
Id
is set asreadonly
, aLogicException
gets thrown.Probably similar to #9538, but in a different code path. I ran into this by directly using
getReference()
, but I suspect the behavior would be exhibited on any proxy relation.Current behavior
LogicException: Attempting to change readonly property Firehed\Entities\Feed::$id. in /var/www/html/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionReadonlyProperty.php:48
Stack:
How to reproduce
Entity:
Table:
Code to cause error:
Expected behavior
Data is loaded fine, var_dump shows the expected value from the db.