什么';在PHP中比较两个对象的最快方法是什么?
假设我有一个对象——在本例中是一个用户对象——我希望能够使用单独的类跟踪对的更改。用户对象不必以任何方式更改其行为,就可以发生这种情况 因此,我的单独类创建一个“干净”的副本,将其存储在本地某个位置,然后稍后可以将用户对象与原始版本进行比较,以查看在其生命周期内是否有任何更改 是否有一个函数、模式或任何东西可以快速比较用户对象的两个版本 选项1 也许我可以序列化每个版本,直接比较,或者散列并比较 选项2 也许我应该简单地创建一个ReflectionClass,运行该类的每个属性,看看这两个版本是否具有相同的属性值 选项3 也许有一个简单的本机函数,比如什么';在PHP中比较两个对象的最快方法是什么?,php,object,Php,Object,假设我有一个对象——在本例中是一个用户对象——我希望能够使用单独的类跟踪对的更改。用户对象不必以任何方式更改其行为,就可以发生这种情况 因此,我的单独类创建一个“干净”的副本,将其存储在本地某个位置,然后稍后可以将用户对象与原始版本进行比较,以查看在其生命周期内是否有任何更改 是否有一个函数、模式或任何东西可以快速比较用户对象的两个版本 选项1 也许我可以序列化每个版本,直接比较,或者散列并比较 选项2 也许我应该简单地创建一个ReflectionClass,运行该类的每个属性,看看这两个版本是
objects\u等于($object1,$object2)代码>
最快的方法是什么?不修改对象的所有(公共、受保护和私有)属性的唯一方法是通过。如果愿意,可以在修改对象之前对其进行修改,然后通过使用反射函数循环两个对象之一的不同属性并比较值来进行比较。这将有效地告诉您哪些属性发生了变化
如果您只想查看对象是否已更改,则可以使用==或===运算符。请看一下PHP文档的一节
也就是说,在更改对象的过程中跟踪您所更改的内容不是更容易吗?php.net上有一个完整的站点,只处理比较对象:
这也是一本好书:
我想说,在复制对象时应该使用“克隆”方法,然后像php.net文章中所说的那样进行比较
另一种快速的方法是在类中声明一个静态方法,该方法只比较相关的“属性”,比如“用户名”、“密码”、“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
}
};
下面是一段支持私有属性的代码:
$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 {
// ...
}
}
请注意,如果$object_1
具有$object_2
没有的属性,则上述代码在尝试访问这些属性时将产生错误
对于这种情况,首先需要将$reflection\u 1->getProperties()
与
$reflection\u 2->getProperties()
通过反射将数据与类进行比较的简单示例
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;
}
}
嗯,我知道我可以序列化这两个对象,并比较散列或其他东西……这不是我是否可以,而是我如何快速完成?我将调整这个问题以反映这种精神……谢谢你的回答:)我可以,但我正在研究教义2,似乎他们创建了一个巨大的对象图,在调用flush()时,他们检查看发生了什么变化,一下子更新所有东西……这就是我想弄明白的。@johnnietheblack-你可以使用条令事件,但这需要稍微修改你的对象。如果您对条令事件感兴趣,请查看。这是针对Doctrine 1.2的,但新版本中的原则是相同的。再次感谢-我不想以任何方式调整用户类,这样我就可以删除“侦听器”,用户就不会知道其中的区别了。另外,我想学习如何做这个w/o原则…一部分是为了好玩,另一部分是如果我需要知道它是如何做的(谢谢:)所以,如果我创建了一个用户的克隆,并更改了其中一个用户的电子邮件地址,那么$User!=$“用户克隆,是吗?”@johnnietheblack——理论上,是这样。我从未尝试过Doctrine,但使用常规类(非Doctrine管理)确实如此。更新非常好,就像我在问题中所说的那样…我希望用户不必更改任何东西以使这种比较成为可能…这就是静态方法存在的原因,要在同一类的对象之间进行交互:)使用此方法,您还可以通过简单地返回一个关联数组,如$result[“username”=>“same”,“password”=>“same”,“cookie”=>“different”]True,快速确定更改了哪个“属性”!我只是不想让我的用户类担心将自己与其他任何东西进行比较,因为它并不真正关心用户。它只应该关注关心用户是否改变的服务……你知道吗?是的,我理解,我曾经为员工做过时间注册。在那里,我使用这个方法比较$time属性,并且每天通过json格式的文件缓存一次。因此,您不必每次都查询员工,只需输出他工作的时间。第二个链接已断开