Мне нужно проверить, равны ли два объекта 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
(должен быть точный объект, чтобы быть правдой), но это нормально.
Однако класс Contact
будет продлен в ближайшее время. Каждый раз, когда я добавляю новые свойства / значения в класс, я должен добавить их в isEqualTo
также. Ничего страшного, но немного громоздко.
Итак, есть ли способ реализовать isEqualTo
автоматически все доступные публичные свойства?
я нашел get_class_vars
а также get_object_vars
но эти методы не будут работать с геттерами и сеттерами, а только с переменными, к которым можно получить прямой доступ.
я нашел get_class_methodes
но это возвращает все методы, а не только геттеры и сеттеры. Фильтрация имен методов по get...
а также set...
будет работать, конечно, но это будет больше похоже на взлом, чем «хороший и чистый» раствор.
Короче: Есть ли «правильный» способ автоматически проверить два объекта PHP на равенство?
Я бы не сказал, что это «правильный» путь, но, поскольку вы не хотите реализовывать / поддерживать свою собственную функцию / метод сравнения, вас может заинтересовать поведение по умолчанию в php, включая сравнение protected / частные свойства:
<?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
);
печать
bool(false)
bool(true)
что может или не может быть достаточно для вас.
Как указал Альма До, циклические ссылки, такие как, например,
<?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
);
вызовет Fatal error: Nesting level too deep - recursive dependency?
,
Вы можете использовать Reflection, но я не думаю, что это хорошая идея. Может быть, serialize () — лучшее решение?
function isEquals(self $obj){
return serialize($obj)===serialize($this)
}