php - 在 ORM 模型中处理脏状态的最佳方式

标签 php model-view-controller oop orm

我不想让任何人说“你不应该重新发明轮子,使用开源 ORM”;我有即时需求,无法切换。

我正在做一个支持缓存的小 ORM。即使不支持缓存,我还是需要这个特性,来知道什么时候将对象写入存储或不写入。模式是 DataMapper。

这是我的方法:

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

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

问题是:有没有办法在每个 setter $this->is_dirty = true"is_dirty"?我的意思是:除了业务逻辑需要更改代码外,大多数时候我都希望 setter 为 $this->attr = $value

其他限制是我不能依赖 __set,因为在具体模型类上,属性已经作为私有(private)属性存在,所以永远不会在 setter 上调用 __set

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

我的一个想法是修改 NetBeans setters 模板,但我认为应该有一种方法可以在不依赖 IDE 的情况下执行此操作。

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

最佳答案

Attention!
My opinion on the subject has somewhat changed in the past month. While the answer where is still valid, when dealing with large object graphs, I would recommend using Unit-of-Work pattern instead. You can find a brief explanation of it in this answer

我有点困惑what-you-call-Model 与 ORM 的关系。这有点令人困惑。特别是因为在 MVC 中,模型 是一个层(至少,thats how I understand it,而您的“模型” 似乎更像Domain Objects)。

我假设您拥有的代码如下所示:

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

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

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

  $mapper->push( $model );

并且,我将假设 what-you-call-Model 有两个方法,供数据映射器使用的设计器:getParameters()setParameters ()。在映射器存储 what-you-call-Model 的状态之前调用 isDirty() 并调用 cleanState() - 当映射器拉数据到 what-you-call-Model

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.

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

  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
  }

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() 方法应该做的事情:

  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;
  }

关于php - 在 ORM 模型中处理脏状态的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10940265/

相关文章:

javascript - 访问 div 标签的值

javascript - 输入类型文本 html5 仅接受 12 个逗号分隔值

node.js - 如何避免 node.js + mongoose 应用程序中的胖模型?

javascript:使用继承 "as is"

javascript - 无法读取数组的属性

php - 从 PHP 脚本接收 'json_encode' 时 Swift JSON 出错。没有它也能正常工作

java - 在模型(MVC)中使用 html 标签是一个坏习惯吗?

javascript - Ember 路由器不更新 Chrome 和 Safari 中的 url

sql - 将关联表中的几列与 SQL 连接一起使用

php - 如何使用php在字符串中用定义的字符替换某些字符?