What's the fastest way to compare two objects in PHP?

别等时光非礼了梦想. 提交于 2020-01-01 08:33:11

问题


Let's say I have an object - a User object in this case - and I'd like to be able to track changes to with a separate class. The User object should not have to change it's behavior in any way for this to happen.

Therefore, my separate class creates a "clean" copy of it, stores it somewhere locally, and then later can compare the User object to the original version to see if anything changed during its lifespan.

Is there a function, a pattern, or anything that can quickly compare the two versions of the User object?

Option 1 Maybe I could serialize each version, and directly compare, or hash them and compare?

Option 2 Maybe I should simply create a ReflectionClass, run through each of the properties of the class and see if the two versions have the same property values?

Option 3 Maybe there is a simple native function like objects_are_equal($object1,$object2);?

What's the fastest way to do this?


回答1:


The only way to access the all (public, protected and private) properties of an object without modifying it is through reflection. You could, if you wanted to, clone the object before it's modified and then compare them by using the reflection functions to loop through the different properties of one of the two objects and comparing values. That would effectively tell you what properties have changed.

If all you care to see is whether or not the objects have changed, you can use the == or === operators. Have a look at the comparing objects section of PHP's documentation.

That said, wouldn't just be easier to keep track of what you've changed as you change them?




回答2:


There is a whole site on php.net only dealing with comparing objects:

http://php.net/manual/en/language.oop5.object-comparison.php

Also a good read:

http://www.tuxradar.com/practicalphp/6/12/0

I would say you should use the "clone" method when copying your object and then later compare as said in the php.net article.

Also a fast way would be by declaring a static method in the class that just compares the relevant "properties" like lets say "username", "password", "cookie",...

    class User
    {

    public $username;
    public $password;
    public $cookie;

    # other code

    public static function compare(&$obj1, &$obj2)
    {
    if ($obj1->username != $obj2->username)
        return 0
    if ($obj1->password != $obj2->password)
        return 0
    if ($obj1->cookie != $obj2->cookie)
        return 0
    return 1
    }


    };       



回答3:


Here is a piece of code that supports private properties:

$reflection_1 = new \ReflectionClass($object_1);
$reflection_2 = new \ReflectionClass($object_2);

$props_1 = $reflection_1->getProperties();

foreach ($props_1 as $prop_1) {

    $prop_1->setAccessible(true);
    $value_1 = $prop_1->getValue($object_1);

    $prop_2 = $reflection_2->getProperty($prop_1->getName());

    $prop_2->setAccessible(true);
    $value_2 = $prop_2->getValue($object_2);

    if ($value_1 === $value_2) {
        // ...
    } else {
        // ...
    }
}


Note that if $object_1 has properties that $object_2 doesn't have, the above code will produce errors when trying to access them.

For such a case, you would need first to intersect $reflection_1->getProperties() with $reflection_2->getProperties().




回答4:


Simple example comparing dto class through reflection

class InvoiceDetails
{
    /** @var string */
    public $type;

    /** @var string */
    public $contractor;

    /** @var string */
    public $invoiceNumber;

    /** @var \DateTimeInterface|null */
    public $saleDate;

    /** @var \DateTimeInterface|null */
    public $issueDate;

    /** @var \DateTimeInterface|null */
    public $dueDate;

    /** @var string */
    public $payment;

    /** @var string */
    public $status;


    public function isEqual(InvoiceDetails $details): bool
    {
        $reflection = new \ReflectionClass(self::class);

        /** @var \ReflectionProperty $property */
        foreach ($reflection->getProperties() as $property) {
            $name = $property->getName();
            if ($this->$name !== $details->$name) {
                return false;
            }
        }

        return true;
    }

}


来源:https://stackoverflow.com/questions/9866920/whats-the-fastest-way-to-compare-two-objects-in-php

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