PHP - hash objects in a way distint object with same fields values have same hash

僤鯓⒐⒋嵵緔 提交于 2021-02-07 19:09:34

问题


I am looking for a way to generate some kind of hash for PHP object (generic solution, working with all classed, built-in and custom, if possible).

SplObjectStorage::getHash is not what I'm looking for, as it will generate different hash for every instance of given class. To picture the problem, let's consider simple class:

class A() {
public $field; //public only for simplicity
}

and 2 instances of that class:

$a = new A(); $a->field = 'b';
$b = new A(); $b->field = 'b';

Every built-in function I've tried will return different hashes for these objects, while I'd like to have some function f($x) with property f($a) == f($b) => $a == $b.

I am aware I could write a function traversing all object's properties recursively until I find a property that can be casted to string, concatenate this strings in fancy way and hash, but the performance of such solution would be awful.

Is there an efficient way to do this?


回答1:


Assuming I understand you correctly, you could serialize the objects then md5 the serialized object. Since the serialization creates the same string if all properties are the same, you should get the same hash every time. Unless your object has some kind of timestamp property. Example:

class A {
    public $field;
}
$a = new A;
$b = new A;
$a->field = 'test';
$b->field = 'test';
echo md5(serialize($a)) . "\n";
echo md5(serialize($b)) . "\n";

output:

0a0a68371e44a55cfdeabb04e61b70f7
0a0a68371e44a55cfdeabb04e61b70f7

Yours are coming out differently because the object in php memory is stored with a numbered id of each instantiation:

object(A)#1 (1) {...
object(A)#2 (1) {...



回答2:


You appear to be talking about a Value Object. It is a pattern where each such object isn't compared according to the object identity, but about the contents - fully, or partially, of the properties that make up the object.

I'm using a number of them in a project:

public function equals(EmailAddress $address)
{
    return strtolower($this->address) === strtolower((string) $address);
}

A more complex object could simply add more items into the comparison function.

return ($this->one === $address->getOne() && 
    $this->two === $address->getTwo());

As such conditionals (all joined with '&&') will short-cut to false as soon as any item does not match.



来源:https://stackoverflow.com/questions/31659187/php-hash-objects-in-a-way-distint-object-with-same-fields-values-have-same-has

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!