PHP程序员站--PHP编程开发平台
 当前位置:主页 >> PHP高级编程 >> 高级应用 >> 

PHP设计模式介绍 第十六章 数据映射模式

PHP设计模式介绍 第十六章 数据映射模式

来源:互联网  作者:  发布时间:2010-05-22
前两章――动态数据模式与表数据网关模式各自展示对记录与每个

接下来,让我们写一些代码来执行它。

class BookmarkMapper {
//...
const INSERT_SQL = “
insert into bookmark (url, name, description,
tag, created, updated)
values (?, ?, ?, ?, now(), now())
“;
public function save($bookmark) {
$rs = $this->conn->execute(
self::INSERT_SQL
,array(
$bookmark->getUrl()
,$bookmark->getName()
,$bookmark->getDesc()
,$bookmark->getGroup()));
}
}

一个对象的常量存储了插入数据的语句,并且代码“自动”把Bookmark 的accessor方法映射到相对应的SQL语句。

现在看起来都齐全了,但是我们还需要做两个事情:处理数据库错误的代码和根据数据库的改变更改初始化的时候设置后者更改$bookmark的属性。

class BookmarkMapper {
//...
public function save($bookmark) {
$rs = $this->conn->execute(
self::INSERT_SQL
,array(
$bookmark->getUrl()
,$bookmark->getName()
,$bookmark->getDesc()
,$bookmark->getGroup()));
if ($rs) {
$inserted = $this->findById($this->conn->Insert_ID());
//clean up database related fields in parameter instance
$bookmark->setId($inserted->getId());
$bookmark->setCrtTime($inserted->getCrtTime());
$bookmark->setModTime($inserted->getModTime());
} else {
throw new Exception(‘DB Error: ‘.$this->conn->errorMsg());


}
}
}

findById() 看起来内容还很少,它的作用是找到并返回匹配ID的Bookmark 实例。本质上来说, BookmarkMapper 用来插入新的Bookmark,从数据库提取数据,并且根据正确的值来设置何时的属性值。而且因为Bookmark 实例自己就是参数并可以被更新,所以必须要返回任何值。

让我们来看下findById()的的详细内容。你可以使用同样的BaseTestCase(前面的Table Data Gateway章节):

class BookmarkMapperTestCase extends BaseTestCase {
// ...
function testFindById() {
$mapper = new BookmarkMapper($this->conn);
$this->addSeveralBookmarks($mapper);
$this->assertIsA(
$bookmark = $mapper->findById(1)
, ‘Bookmark’);
$this->assertEqual(1, $bookmark->getId());
}
}

从技术上来说,addSeveralBookmarks() 必须等待findById()工作正常再开始工作。(看save()方法里面的代码就知道了),我们等下再来研究addSeveralBookmarks()。

class BookmarkMapper {
// ...
public function findById($id) {
$row = $this->conn->getRow(
‘select * from bookmark where id = ?’
,array((int)$id)
);
if ($row) {
$bookmark = new Bookmark($this);
foreach($this->map as $field) {
$setprop = (string)$field->mutator;
$value = $row[(string)$field->name];
if ($setprop && $value) {
call_user_func(array($bookmark, $setprop), $value);
}
}
return $bookmark;
} else {
return false;
}
}
}

因为设计模式里面每一个finder 方法都需要把一个数据库的行转变为一个Bookmark 实例,所以我们需要为了实现这个功能在创建一个新的方法,命名为

createBookmarkFromRow()。
class BookmarkMapper {
// ...
protected function createBookmarkFromRow($row) {
$bookmark = new Bookmark($this);
foreach($this->map as $field) {
$setprop = (string)$field->mutator;
$value = $row[(string)$field->name];
if ($setprop && $value) {
call_user_func(array($bookmark, $setprop), $value);
}
}
return $bookmark;
}
}

通过这个方法,我们对findById()进行简化:

class BookmarkMapper {
// ...
public function findById($id) {
$row = $this->conn->getRow(
‘select * from bookmark where id = ?’
,array((int)$id)
);
if ($row) {
return $this->createBookmarkFromRow($row);
} else {
return false;
}
}
}

所以上面阐述的内容有些复杂了,所以一个UML的流程图可以让你更容易了解。

首先,数据从数据库提取出来;随后,建立一个Bookmark的实例。然后,对于映射的每一个部分,代码找到合适的setter方法并把数据行的值传递给setter方法。Bookmark实例,添加了数据库的数据后,用findById()取出。

现在,让我们看下BookmarkMapper::add()方法,通过BaseTestCase::addSeveralBookmarks()实现。通过一个测试用例,我们可以发现他们都是在表里面创建一个新的行并且返回Bookmark类的一个拥有实际数据的实例。

class BookmarkMapperTestCase extends BaseTestCase {
// ...
function testAdd() {
$mapper = new BookmarkMapper($this->conn);
$bookmark =
$mapper->add(
‘http://phparch.com’,
‘php|arch’,
‘php|architect magazine homepage’,
‘php’);
$this->assertEqual(1,
$this->conn->getOne(‘select count(1) from bookmark’));
$this->assertEqual(‘http://phparch.com’, $bookmark->getUrl());
$this->assertEqual(‘php|arch’, $bookmark->getName());
$this->assertEqual(‘php|architect magazine homepage’,
$bookmark->getDesc());
$this->assertEqual(‘php’, $bookmark->getGroup());
}
}

这里是BookmarkMapper 的相关代码。

class BookmarkMapper {
// ...
public function add($url, $name, $description, $group) {
$bookmark = new Bookmark;
$bookmark->setUrl($url);
$bookmark->setName($name);
$bookmark->setDesc($description);
$bookmark->setGroup($group);
$this->save($bookmark);
return $bookmark;
}
}

这个与动态的记录ActiveRecordTestCase::add()是很类似的,方便使用。但是这里它已经被加入到数据映射里面而不是测试用例,这样在整个项目里面都可以使用它。


延伸阅读:
从魔兽看PHP设计模式
《PHP设计模式介绍》导言
PHP设计模式介绍 第一章 编程惯用法
PHP设计模式介绍 第二章 值对象模式
PHP设计模式介绍 第三章 工厂模式
PHP设计模式介绍 第四章 单件模式
PHP设计模式介绍 第五章 注册模式
PHP设计模式介绍 第六章 伪对象模式
PHP设计模式介绍 第七章 策略模式
PHP设计模式介绍 第八章 迭代器模式
PHP设计模式介绍 第九章 观测模式
PHP设计模式介绍 第十章 规范模式
PHP设计模式介绍 第十一章 代理模式
PHP设计模式介绍 第十二章 装饰器模式
PHP设计模式介绍 第十三章 适配器模式
PHP设计模式介绍 第十四章 动态记录模式
PHP设计模式介绍 第十五章 表数据网关模式

最新文章
推荐阅读
月点击排行榜
PHP程序员站 Copyright © 2007-2010,PHPERZ.COM All Rights Reserved 粤ICP备07503606号