11

Specifics

First, the definition of "equality" in my case is - that objects are equal when they have same structure and values for that structure. However, they may be not same instance, or properties may be not in same "order" (I mean, as they were assigned/defined). There are similar questions here on SO, like this - but they are not covering my case.

I need to compare entities in PHP due to testing of my code purposes - and those entities might be anything. In particular, they may be objects. Objects comparison, however, is not "safe". Imagine that you are comparing:

$result = $objectX == $objectY;

And this may lead to fatal error in case when objects have circular references. Simple example for it I prepared here. As we can see, PHP tries to follow nested levels and fails in infinite loop - because by nature objects are same in content, but have circular references.

Important detail is that objects might contain non-serializable stuff (like closures), which makes impossible to rely on "seralize/unserialize" approach (even if to forget about unordered comparison)

Current approach

I have the code like this (quite too much to paste directly here, but just in case, here is a gist) - so I am performing DFS there and catching situations with such circular references. As you can see, it's quite complex - and, by the way, it is slow.

Another issue with current approach is - that when there are arrays inside objects, they will be compared with respect of elements order, which, in some cases, is not fine for me (ideal case - when I'll be able to switch order-wise comparison), but to overcome it natively, I probably will need to "sort" arrays somehow - and I have no idea how to do that - as, again, comparison of those arrays elements will not be safe.

And, more, circular arrays references will also cause failure:

$array = ['foo', $object, &$array];

Question

What could be other (better) approaches to resolve a matter? Serializing objects might be the case, but due to non-ordered set of properties it will fail for me.

Community
  • 1
  • 1
Alma Do
  • 37,009
  • 9
  • 76
  • 105

1 Answers1

1

Do you know Doctrine\Common\Util\Debug::export($class, $maxDepth) ?

That method "export" prevents you from infinite loop and return an array witch can be used to make diff.

Beyond a certain depth, it is not necessary to go further and with $maxDepth you can specify the "accuracy" of your comparison.

Bang
  • 919
  • 4
  • 11
  • Looking to the [code](http://www.doctrine-project.org/api/common/2.3/source-class-Doctrine.Common.Util.Debug.html#24-136) I see that this method is designed to rely on `$maxDepth` and will fail if that was not set. By "fail" I mean that it will not do any useful work, just print out class name and that's it. – Alma Do Feb 09 '15 at 10:34