Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare objects on equality in PHP

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.

like image 947
Alma Do Avatar asked Feb 06 '15 09:02

Alma Do


People also ask

How do you check if two objects are equal in PHP?

PHP has a comparison operator == using which a simple comarison of two objecs variables can be performed. It returns true if both belong to same class and values of corresponding properties are are same.

How do you compare two objects using the equal method?

In the first comparison, equals() compares the current object instance with the object that has been passed. If the two objects have the same values, equals() will return true . In the second comparison, equals() checks to see whether the passed object is null, or if it's typed as a different class.

What is == and === in PHP?

== Operator: This operator is used to check the given values are equal or not. If yes, it returns true, otherwise it returns false. Syntax: operand1 == operand2. === Operator: This operator is used to check the given values and its data type are equal or not.

How is the comparison of objects done in PHP difference between == and === operator?

When we use those operators to compare objects, == will check if the two objects have the same class and have the same values assigned to them. === on the other hand will check if they also refer to the same instance (object).


1 Answers

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.

like image 156
Bang Avatar answered Sep 18 '22 10:09

Bang