mongodb-odm icon indicating copy to clipboard operation
mongodb-odm copied to clipboard

Change detection doesn't work with objects and custom types

Open MidnightDesign opened this issue 8 years ago • 9 comments

I've got a property $foo on my document that holds a mutable object. That object is converted to an array by a custom type when persisting the document. Unfortunately, when I change a property on that mutable object, $foo isn't recognized as having changed because of this condition:

if ($orgValue === $actualValue) {
    // ...
   continue;
    // ...
}

It's still the same instance, and so the contition evaluates to true.

Is there a better way to detect changes? Maybe something like comparing two spl_object_hash()es?

MidnightDesign avatar Aug 03 '16 14:08 MidnightDesign

spl_object_hash() gave us enough headache with embedded documents since they can be reused, I'm not sure I would like to follow that way... As a temporary solution I'd recommend using immutable objects while we try to figure out a way to fix the bug.

malarzm avatar Aug 03 '16 19:08 malarzm

Thanks, I already changed it to be immutable.

MidnightDesign avatar Aug 03 '16 19:08 MidnightDesign

Just to update, so far I have no idea how this could be introduced in a bugfix manner...

Offhand I recalled there was #976 (but that'd be feature) and also I have an idea for 2.0 that could fix the issue at hand, namely I'm pondering over using database values for preparing change sets.

malarzm avatar Aug 05 '16 20:08 malarzm

Hi!, happy 1 year anniversary for this issue. This particular issue has long vexed me in one of my projects. We use value objects extensively and in our world a value object with the same values should evaluate to be equal to a different value object with the same values.

I think ODM should make use of an interface offered in Common that mimics an interface never accepted into PHP core: https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Comparable.php

This code block could check if $orgValue implements Comparable, if so, use the compareTo($other) method. If not, default to === check.

wesnick avatar Aug 06 '17 15:08 wesnick

This is actually interesting, I had no idea such interface exists :) Given our current plans for 2.0 it indeed might be feasible to add as a feature earlier. @alcaeus @jmikola any downsides coming to your mind? From my perspective it can get into our way later if we'd like to remove the Comparable approach.

malarzm avatar Aug 06 '17 16:08 malarzm

The Comparable interface looks like a good option here. I recall @guilhermeblanco trying to get this into core some time ago, but I wasn't aware it was added to Doctrine Common. Let's confirm if ORM is using it to address the same use case here.

/cc @beberlei

jmikola avatar Aug 06 '17 16:08 jmikola

@jmikola you need to work on your summoning abilities a bit ;)

Using the comparable interface would make sense - we could compare the objects using === if one of them doesn't implement Comparable and use that if both of them do. I'm moving this to the 2.0 milestone since I don't think I'll get to it before 1.2, which I'm trying to wrap up asap.

alcaeus avatar Oct 01 '17 04:10 alcaeus

The issue has been reported almost 4 years ago. A good solution (using the Comparable interface) has been proposed three years ago. The problem has still not been solved? Is this really true or am I missing something?

Is there any other solution for this?

SDPrio avatar May 06 '20 08:05 SDPrio

The problem has still not been solved?

Indeed it hasn't. If you're up for it, we're happy to assist while you create the pull request.

alcaeus avatar May 06 '20 11:05 alcaeus