在ORM模型中处理脏状态的最佳方法 [英] Best way to handle dirty state in an ORM model

查看:80
本文介绍了在ORM模型中处理脏状态的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不希望有人说"",您不应该重新发明轮子,使用开放源代码的ORM" ;我有即时要求,无法切换.

I don't want anyone saying "you should not reinvent the wheel, use an open source ORM"; I have an immediate requirement and cannot switch.

我正在做一点ORM,它支持缓存.即使不支持缓存,无论如何我仍然需要此功能,以了解何时将对象写入存储.模式是DataMapper.

I'm doing a little ORM, that supports caching. Even not supporting caching, I would need this feature anyways, to know when to write an object to storage or not. The pattern is DataMapper.

这是我的方法:

  • 我想避免运行时自省(即猜测属性).
  • 我不想使用CLI代码生成器来生成getter和setter(确实是使用ALT + INSERT使用NetBeans).
  • 我希望模型最接近POPO(普通的旧PHP对象).我的意思是:私有属性,每个属性的硬编码"获取器和设置器.

我有一个名为AbstractModel的Abstract类,所有模型都继承该类.它具有一个称为isDirty()的公共方法,该方法具有一个称为is_dirty的私有(如果需要的话,也可以受到保护)属性.它必须返回true或false,这取决于对象数据自加载以来是否发生了变化.

I have an Abstract class called AbstractModel that all the models inherit. It has a public method called isDirty() with a private (can be protected too, if needed) attribute called is_dirty. It must return true or false depending if there is a change on the object data or not since it was loaded.

问题是:有没有一种方法可以引发内部标志"is_dirty"而无需在每个设置器$this->is_dirty = true中进行编码?我的意思是:除了业务逻辑需要更改代码之外,我大部分时间都希望将setter设置为$this->attr = $value.

The issue is: is there a way to raise the internal flag "is_dirty" without coding in each setter $this->is_dirty = true? I mean: I want to have the setters as $this->attr = $value most of the time, except a code change is needed for business logic.

其他限制是,我不能依赖__set,因为在具体的模型类上,属性已经作为私有存在,所以在设置方法上永远不会调用__set.

Other limitation is that I cannot rely on __set because on the concrete model class the attributes already exists as private, so __set is never called on the setters.

有什么想法吗?接受其他ORM的代码示例.

Any ideas? Code examples from others ORMs are accepted.

我的想法之一是修改NetBeans setters模板,但是我认为应该有一种不依赖于IDE的方法.

One of my ideas was to modify the NetBeans setters template, but I think there should be a way of doing this without relying on the IDE.

我想到的另一个想法是创建设置器,然后用下划线或其他内容更改private属性的名称.这样,setter会调用__set并在那里有一些代码来处理"is_dirty"标志,但是这有点破坏了POPO的概念,而且很丑陋.

Another thought I had was creating the setters and then change the private attribute's name with an underscore or something. This way the setter would call to __set and have some code there to deal with the "is_dirty" flag, but this breaks the POPO concept a little, and it's ugly.

推荐答案

注意!
在过去的一个月里,我对这个问题的看法有所改变.尽管答案仍然有效,但是在处理大型对象图时,我建议改为使用工作单元模式.您可以在 此答案

我有点困惑您叫什么模型与ORM有何关系.这有点令人困惑.特别是由于在MVC中,模型是一层(至少,这就是我的理解方式,而您的模型" 似乎更像是域对象)

I'm kinda confused how what-you-call-Model is related to ORM. It's kinda confusing. Especially since in MVC the Model is a layer (at least, thats how I understand it, and your "Models" seem to be more like Domain Objects).

我将假设您拥有的是一个看起来像这样的代码:

I will assume that what you have is a code that looks like this:

  $model = new SomeModel;
  $mapper = $ormFactory->build('something');

  $model->setId( 1337 );
  $mapper->pull( $model );

  $model->setPayload('cogito ergo sum');

  $mapper->push( $model );

而且,我将假设您叫什么模型有两种方法,供数据映射器使用的设计器:getParameters()setParameters().并且您在映射器存储您要调用的模型的状态之前调用isDirty()并调用cleanState()-当映射器将数据提取到您要调用的模型 .

And, i will assume that what-you-call-Model has two methods, designer to be used by data mappers: getParameters() and setParameters(). And that you call isDirty() before mapper stores what-you-call-Model's state and call cleanState() - when mapper pull data into what-you-call-Model.

BTW,如果您有更好的建议从而不是setParameters()getParameters()到数据映射器获取值,请分享,因为我一直在努力提出更好的建议.在我看来,这就像封装泄漏.

BTW, if you have a better suggestion for getting values from-and-to data mappers instead of setParameters() and getParameters(), please share, because I have been struggling to come up with something better. This seems to me like encapsulation leak.

这将使数据映射器方法看起来像:

This would make the data mapper methods look like:

  public function pull( Parametrized $object )
  {
      if ( !$object->isDirty() )
      {
          // there were NO conditions set on clean object
          // or the values have not changed since last pull
          return false; // or maybe throw exception
      }

      $data = // do stuff which read information from storage

      $object->setParameters( $data );
      $object->cleanState();

      return $true; // or leave out ,if alternative as exception
  }

  public static function push( Parametrized $object )
  {
      if ( !$object->isDirty() )
      {
          // there is nothing to save, go away
          return false; // or maybe throw exception
      }

      $data = $object->getParameters();
      // save values in storage
      $object->cleanState();

      return $true; // or leave out ,if alternative as exception
  }

在代码片段Parametrized中是接口的名称,该接口应实现.在这种情况下,方法getParameters()setParameters().它的名字如此奇怪,因为在OOP中,implements词表示 具有 ,而extends词表示 是- .

In the code snippet Parametrized is a name of interface, which object should be implementing. In this case the methods getParameters() and setParameters(). And it has such a strange name, because in OOP, the implements word means has-abilities-of , while the extends means is-a.

到目前为止,您应该已经拥有了所有类似的东西...

现在,这是isDirty()cleanState()方法应该执行的操作:

Now here is what the isDirty() and cleanState() methods should do:

  public function cleanState()
  {
      $this->is_dirty = false;
      $temp = get_object_vars($this);
      unset( $temp['variableChecksum'] );
      // checksum should not be part of itself
      $this->variableChecksum = md5( serialize( $temp ) );
  }

  public function isDirty()
  {
      if ( $this->is_dirty === true )
      {
          return true;
      }

      $previous = $this->variableChecksum;

      $temp = get_object_vars($this);
      unset( $temp['variableChecksum'] );
      // checksum should not be part of itself
      $this->variableChecksum = md5( serialize( $temp ) );

      return $previous !== $this->variableChecksum;
  }

这篇关于在ORM模型中处理脏状态的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆