在PHP中,跟踪对象状态的最佳方法是什么,判断它是否已被修改?我有一个创建新实体的存储库对象,然后由其他组件读取/修改它们,最终返回到存储库。如果对象已更改,我希望存储库将数据保存回持久存储(DB)。
我可以想到四个选项:
从对象中取出对象的克隆并比较它们的内容(比听起来更复杂,因为你怎么知道哪个克隆要比较对象?)
...或
其他一些我不知道的聪明伎俩?
谢谢,
千斤顶
答案 0 :(得分:3)
选项1 - 使用布尔标志 - 是最好的方法。在性能,以及一般可用性和可移植性方面。
所有其他选项都会产生过多的开销,在这种情况下根本不需要。
答案 1 :(得分:1)
您可能希望查看Unit of Work模式,因为这是它旨在解决的问题。当对象发生变化时,它们会向UoW注册自己或被动注册,UoW负责跟踪哪些对象已被更改,以及确定在游戏结束时需要将哪些内容保存回数据库。
答案 2 :(得分:1)
首先,我通常认为$ modified或$ dirty属性是最好的解决方案。
但我写作的原因是你的评论是
如果有很多二传手,那就太乏味了
我想知道你是不是在使用PHP5?
如果你是,这是__set()魔术方法的完美使用。您甚至可以按原样使用它,从__set()方法调用现有的setter。
例如:
class some_concept
{
private $x = 1;
private $y = 2;
private $dirty = false;
// This represents your existing setter methods
function set_y($i)
{
$this->y = $i;
}
function __set($name, $value)
{
if ($value != $this->{$name}) $this->dirty = true;
return $this->{'set_' . $name}($value);
}
function __get($name)
{
return $this->{$name};
}
}
但是,您对比较序列化字符串的想法有一些优点。序列化可能很昂贵。这是真的。
但它是您列表中最准确的解决方案。想象一下,加载上面的对象,将$ y设置为0,然后将其设置回2,然后保存。它脏了吗?它会这样说,但实际上,它处于加载时的状态。
我在这里使用的测试是你的save()有多贵。如果保存是一个非常昂贵的API调用,数据库事务等,那么您可能会发现在加载时序列化对象并保存它的md5哈希是值得的。
如果那个需要几分之一秒的操作可以节省多秒的交易,那么它真的值得。
最后,我想指出Damien Katz对这一主题的反对意见。 Katz是一位才华横溢的开发人员,他创建了CouchDb,目前在MySQL工作。
他的Error Codes v Exceptions帖子篇幅很长,但对此话题的阅读非常好。
虽然它开始讨论返回抛出异常的错误代码的优点,但他最终还是谈到了如何编写可靠的软件。
首先,他讨论了如何以与SQL事务相同的方式创建原子类。一般的想法是你制作一个对象的副本,修改它的状态,并且只有在最后一步,如果成功,你是否将该副本交换为主要对象。这允许有意义的撤消功能。像这样的模式虽然难以融入现有的应用程序,但也提供了这个is_modified问题的解决方案。
答案 3 :(得分:0)
我认为第一个选项最适合更易读的代码和更快的执行。我还会考虑首先序列化对象(比如文件),然后对内容进行散列。
相同的内容应该产生相同的哈希值。