Data Mapper通常是什么样的?

时间:2009-12-28 17:46:13

标签: php orm datamapper

我有一个名为Cat的表,以及一个名为Cat的PHP类。现在我想创建一个CatDataMapper类,以便Cat extends CatDataMapper

我希望Data Mapper类提供执行ORM以及创建,编辑和删除Cat的基本功能。

为此目的,也许知道这种模式的人可以给我一些有用的建议吗?我觉得提供像update(),delete(),save()这样的函数会有点简单。

我意识到数据映射器有这个问题:首先你创建了Cat的实例,然后初始化所有的变量,比如name,furColor,eyeColor,purrSound,meowSound,atte者等等。在设置好所有内容后,你调用从CatDataMapper继承的save()函数。这很简单;) 但现在,真正的问题是:你在数据库中查询猫并获得一个包含大量猫数据的无聊结果集。

PDO具有一些ORM功能来创建Cat实例。让我说我使用它,或者甚至说我有一个带有关联数组的mapDataset()函数。但是,只要我从数据集中获取Cat对象,就会有冗余数据。同时,20个用户可以从数据库中获取相同的cat数据并编辑cat对象,即重命名cat,并保存()它,而另一个用户仍然需要设置另一个furColor。当所有人都保存他们的编辑时,一切都搞砸了。

呃...好吧,保持这个问题非常简短:这里有什么好的做法?

5 个答案:

答案 0 :(得分:12)

来自DataMapper in PoEA

  

Data Mapper是一个软件层   分隔内存中的对象   来自数据库。它的责任   是在两者之间传输数据   并将它们与每个人隔离开来   其他。使用Data Mapper在内存中   物体甚至不需要知道   存在的数据库;他们不需要SQL   接口代码,当然没有   了解数据库模式。 (该   数据库架构总是一无所知   使用它的对象。)因为它是一个   Mapper的形式(473),数据映射器   本身甚至都不为人所知   层

因此,Cat不应该扩展CatDataMapper,因为这会创建一个is-a关系并将Cat绑定到持久层。如果您希望能够以这种方式处理Cats的持久性,请查看ActiveRecord或任何其他数据源架构模式。

使用域模型时,通常使用DataMapper。一个简单的DataMapper只是在一个字段到字段的基础上将数据库表映射到等效的内存中类。但是,当出现对DataMapper的需求时,通常不会有这样简单的关系。表格不会将1:1映射到您的对象。相反,多个表可以形成一个Object Aggregate而反之亦然。因此,实现只是 CRUD方法很容易成为一个挑战。

除此之外,它是更复杂的模式之一(在PoEA中涵盖15页),通常与Repository pattern等组合使用。请查看本页右侧的相关问题栏以了解类似问题。

关于有关多个用户编辑同一个Cat的问题,这是一个名为Concurrency的常见问题。一个解决方案是locking the row,而有人编辑它。但就像所有事情一样,这可以lead to other issues

答案 1 :(得分:2)

如果您依赖于DoctrinePropel之类的ORM,基本原则是创建一个静态类,从数据库中获取实际数据(例如Propel将创建CatPeer),以及然后,Peer类检索的结果将“水合”到Cat对象中。

水化过程是将“无聊的”MySQL结果集转换为具有getter和setter的漂亮对象的过程。

因此,对于检索,您可以使用CatPeer::doSelect()之类的内容。然后,对于一个新对象,您首先要实例化它(或从数据库中检索和实例): $cat = new Cat();

插入操作就像执行一样简单:$cat->save();这等同于插入(或者如果对象已经存在于db中则更新... ORM应该知道如何区分例如,使用存在或不存在主键的新对象和现有对象。

答案 2 :(得分:2)

在PHP中实现数据映射器非常困难< 5.3,因为你无法读/写protected / private字段。加载和保存对象时有几个选择:

  1. 使用某种解决方法,例如序列化对象,修改它的字符串表示形式,然后使用unserialize将其恢复原状
  2. 公开所有字段
  3. 保持私密/受保护,并为每个人编写变更器/访问器
  4. 第一种方法有可能破坏新版本,并且是非常粗糙的黑客,第二种方法被认为是(非常)不好的做法。

    第三个选项也被认为是不好的做法,因为你不应该为所有字段提供getter / setter,只提供需要它的字段。您的模型从纯DDD(域驱动设计)角度“受损”,因为它包含仅由于持久性机制而需要的方法。 这也意味着现在你必须描述字段的另一个映射 - > setter方法,在字段旁边 - >表格列。

    PHP 5.3引入了使用反射访问/更改所有类型字段的功能:

    http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php

    有了这个,您就可以实现真正的数据映射器,因为为所有字段提供mutator的需求已经停止。

答案 3 :(得分:1)

  

PDO具有一些ORM功能   创建Cat实例。让我说我用   那,或者甚至说我有一个   需要一个mapDataset()函数   关联数组。但是,一旦   我从数据集中获取了我的Cat对象,我   有冗余数据。同时,   二十个用户可以拿起相同的   cat数据来自数据库并进行编辑   猫对象,即重命名猫,   并保存()它,而另一个用户   关于设置另一个的事情   furColor。当他们全部保存他们的   编辑,一切都搞砸了。

为了通常跟踪数据的状态,将使用IdentityMap和/或UnitOfWork跟踪映射实体上的所有不同操作......以及请求周期结束时,操作将是进行。

答案 4 :(得分:0)

保持答案简短: 你有一个Cat的实例。 (也许它扩展了CatDbMapper或Cat3rdpartycatstoreMapper) 你打电话:

$cats = $cat_model->getBlueEyedCats();
//then you get an array of Cat objects, in the $cats array

不知道你使用了什么,你可能会看一些php框架以便更好地理解。