Thanks to visit codestin.com
Credit goes to github.com

Skip to content

EntityManager::find() calls UnitOfWork::registerManaged() twice and that causes Change Detection to fail #10880

@eXsio

Description

@eXsio

BC Break Report

Q A
BC Break yes
Version 2.16.0

Summary

I have a Symfony 5.4 based Application that uses Framework Extra Bundle and its Param Converter feature. After upgrading from 2.15.3 to 2.16.0 Doctrine has stopped detecting Entity Changes in Entities loaded by the ParamConverter, due to the new logic introduced by this commit: 01a1432

After some snooping I've found out, that the UnitOfWork::registerManaged() is actually called twice:

The second call rewrites previously loaded/hydrated Entity and sets the UnitOfWork::$originalEntityData property to []. This causes the change detection to fail, because the UoW is not able to correctly compare the Actual Data to the Original Data.

The Framework Extra Bundle uses the EntityManager::find() method under the hood, so I wouldn't blame the lib for the failure. The fact is that Doctrine has altered it's behavior significantly because of that change.

Previous behavior

when an Entity wired by the ParamConverter was changed, Doctrine has correctly detected changes made in the Entity.

Current behavior

Doctrine doesn't detect changes in the Entities wired by the ParamConverter.

How to reproduce

  1. Create a Symfony 5.4 Application with Framework Extra Bundle
  2. Autowire an Entity to a Controller
  3. change the Entitie's state and save
  4. change detection fails

I am not sure if this is the case for every such configuration, but I am positive that the UnitOfWork::registerManaged method can be called twice for a single createEntity method call.

Suggested Fix

Any tampering with not calling the UnitOfWork::registerManaged() a second time has caused the ORM to blow up in some other place. However, modifying the UnitOfWork::registerManaged() method itself to not allow to overwrite the Entity seems to have helped:

   public function registerManaged($entity, array $id, array $data)
    {
        $oid = spl_object_id($entity);
        //don't allow to overwrite Entity once it has been registered
        if(array_key_exists($oid, $this->entityIdentifiers)) {
            return;
        }
        ....

P.S.

This is not the only regression caused by this change. I can also see multiple tickets that point to this change as a culprit. Don't mean to tell you how to do things, but this seems like a very impactful and drastic change for a minor release.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions