Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/244.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 自动检查两个对象是否相等?_Php_Class_Object_Equality - Fatal编程技术网

Php 自动检查两个对象是否相等?

Php 自动检查两个对象是否相等?,php,class,object,equality,Php,Class,Object,Equality,我需要检查两个PHP对象的值是否相等。当然,我可以很容易地向类添加一个比较所有相关值的isEqualTo(…)方法。然而,混凝土类在不久的将来将会改变,我想知道是否有任何自动化的方法来做到这一点 例如: class Contact { private name; // String private phone; // Int private someObject; // Custom Object public function getNa

我需要检查两个PHP对象的值是否相等。当然,我可以很容易地向类添加一个比较所有相关值的
isEqualTo(…)
方法。然而,混凝土类在不久的将来将会改变,我想知道是否有任何自动化的方法来做到这一点

例如:

class Contact {
    private name;       // String
    private phone;      // Int
    private someObject; // Custom Object

    public function getName() {
        return $this->name;
    }

    public function setName($newName) {
        $this->name = $newName;
    }


    public function getPhone() {
        return $this->phone;
    }

    public function setPhone($newPhone) {
        $this->phone = $newPhone;
    }


    public function getSomeObject() {
        return $this->someObject;
    }

    public function setSomeObject($newObj) {
        $this->someObject = $newObj;
    }


    // Manual Solution 
    public function isEqualTo($contact) {
         result  = $this->name == $contact->getName();
         result &= $this->phone == $contact->getPhone();

         result &= $this->someObject == $contact->getSomeObject();

         return result;
    }
} 
这显然是可行的。当然,我知道比较
someObject
的局限性(需要精确到someObject才是真的),但这是可以的

但是,在不久的将来,将扩展类别
联系人
。每次我向类添加新属性/值时,我也必须将它们添加到
isEqualTo
。没什么大不了的,只是有点麻烦

那么,有没有办法实现
isEqualTo
以自动生成所有可用的公共属性

我发现了
get_class_vars
get_object_vars
,但是这些方法不适用于getter和setter,而只适用于可以直接访问的vars

我找到了
get\u class\u方法
,但它返回所有方法,而不仅仅是getter和setter。当然,通过
get…
set…
过滤方法名称是可行的,但这更像是一种黑客行为,而不是一种“干净、漂亮”的解决方案


简而言之:有没有什么“正确”的方法可以自动检查两个PHP对象是否相等?

我不会说这是“正确”的方法,但是,由于您不想实现/维护自己的比较函数/方法,您可能会对php的默认行为感兴趣,包括受保护/私有属性的比较:

<?php
class Foo {
    private $x,$y,$z;
    public function __construct($x,$y,$z) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);

var_dump(
    $f1==$f2,
    $f1==$f3
);
这对你来说可能足够,也可能不够


例如,循环引用,例如

<?php
class Foo {
    private $x,$y,$z;
    public function __construct($x,$y,$z) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }

    public function setZ($z) {
        $this->z = $z;
    }
}


$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);

$f1->setZ($f3);
$f3->setZ($f1);


var_dump(
    $f1==$f2,
    $f1==$f3
);

您可以使用反射来完成此操作,但我认为这不是一个好主意。也许serialize()是更好的解决方案

function isEquals(self $obj){
return serialize($obj)===serialize($this)
}

这将在循环引用上失败(以错误的方式,导致致命错误)。这一点在使用它时必须记住。我将把这一点添加到答案中(还有其他问题,但这可能是最明显和最引人注目的)。嗯,“循环引用”-我指的不仅仅是狭义的对象大小写。不能有交叉对象引用,甚至可以有交叉属性(或内联属性)递归。没有嵌套对象的示例案例是数组,如上所示。因此,您的示例是有效的,我只是注意到在比较上遍历递归结构在PHP中工作得不好。缓解这种情况的常用方法是使用DFS和定制用户功能(通过对象反射)
function isEquals(self $obj){
return serialize($obj)===serialize($this)
}