到目前为止,这些实验已证明了以下事实:属性可以被设置,save()能正常工作,$ID属性已被置为1。让我们进一步的深入到数据表去验证其它的属性值也被正确的保存。
class ActiveRecordTestCase extends UnitTestCase { // ... function testNew() { $link = new Bookmark; $link->url = ‘http://simpletest.org/’; $link->name = ‘SimpleTest’; $link->description = ‘SimpleTest project homepage’; $link->tag = ‘testing’; $link->save(); $this->assertEqual(1, $link->getId()); // fetch the table as an array of hashes $rs = $this->conn->getAll(‘select * from bookmark’); $this->assertEqual(1, count($rs), ‘returned 1 row’); foreach(array(‘url’, ‘name’, ‘description’, ‘tag’) as $key) { $this->assertEqual($link->$key, $rs[0][$key]); } } } |
以上突出显示代码的功能是获取整个书签表数据。GetAll()方法执行查询并返回结果集,该结果集是以数组形式存放的记录的哈稀表。AssertEqual()方法验证只有一条记录存在于结果集中。通过foreach循环比较从数据表中取得记录的字段与$link对象的属性值是否一致。
上述代码已能正常工作,但通过手工的方法设定属性值去增加书签表数据的方法还是略显繁琐。因此,为上述的案例增加一个方便(通用)的方法,来实现增加的新建书签对象。
The ActiveRecordTestCase::add()方法带有(处理)四个参数,可建立与插入一个新的ActiveRecord书签对象。如果你在后续实验中要用到新创建的书签对象,add()方法还可以在创建成功后返回它。
class ActiveRecordTestCase extends UnitTestCase { // ... function add($url, $name, $description, $tag) { $link = new Bookmark; $link->url = $url; $link->name = $name; $link->description = $description; $link->tag = $tag; $link->save(); return $link; } } |
你完全可以在本实验案例中写一个测试方法来证明其可用性。
class ActiveRecordTestCase extends UnitTestCase { // ... function testAdd() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $rs = $this->conn->execute(‘select * from bookmark’); $this->assertEqual(2,$rs->recordCount()); $this->assertEqual(2,$this->conn->Insert_ID()); } } |
既然书签可以创建并存储于数据库中,让我们给Active Record书签对象增加一个方法,可以简单的从数据库中获取数据并在实例的属性中保存所获取的值。一种通用的建立动态记录对象的技术是通过传递一个标示符,如书签号(或是别的什么标准)到它的构造函数中,并且从数据库中取出与这个ID相关联的行数据。
class ActiveRecordTestCase extends UnitTestCase { // ... function testCreateById() { $link = $this->add( ‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $this->assertEqual(1, $link->getId()); $link2 = new Bookmark(1); $this->assertIsA($link2, ‘Bookmark’); $this->assertEqual($link, $link2); } } |
这个实验传递了一个ID到构造函数,这是前面的实验所没有出现过的。是否传递ID是可选的,如果没有传递ID,则前述试验中建立新的空书签实例的功能将依然正常工作。
这儿是一些实现上述功能要求的代码。
class Bookmark { // ... const SELECT_BY_ID = ‘select * from bookmark where id = ?’; public function __construct($id=false) { $this->conn DB::conn(); if ($id) { $rs = $this->conn->execute( self::SELECT_BY_ID ,array((int)$id)); if ($rs) { $row = $rs->fetchRow(); foreach($row as $field => $value) { $this->$field = $value; } } else { trigger_error(‘DB Error: ‘.$this->conn->errorMsg()); } } } // ... } |
构造函数允许一个名为$id的参数,它的默认为假。如果传来的参数不为假,则BOOKmark则用此ID为关键字查询数据库中BOOKmark表的相关行,如果该行存在,则用获取的数据来设定对象属性的值。
数据错误测试
Mock::generate(‘ADOConnection’); class ActiveRecordTestCase extends UnitTestCase { //... function testDbFailure() { $conn = new MockADOConnection($this); $conn->expectOnce(‘execute’, array(‘*’,’*’)); $conn->setReturnValue(‘execute’,false); $conn->expectOnce(‘errorMsg’); $conn->setReturnValue(‘errorMsg’, ‘The database has exploded!!!!’); } } |
这段代码调用了Mock::generate() 来生成一个MockADOConnection 类,并生成一个模拟连接的实例,同时设定一些基本的返回值来指明错误,和定义在这些环境中可能会出现的意外。
延伸阅读:
从魔兽看PHP设计模式
《PHP设计模式介绍》导言
PHP设计模式介绍 第一章 编程惯用法
PHP设计模式介绍 第二章 值对象模式
PHP设计模式介绍 第三章 工厂模式
PHP设计模式介绍 第四章 单件模式
PHP设计模式介绍 第五章 注册模式
PHP设计模式介绍 第六章 伪对象模式
PHP设计模式介绍 第七章 策略模式
PHP设计模式介绍 第八章 迭代器模式
PHP设计模式介绍 第九章 观测模式
PHP设计模式介绍 第十章 规范模式
PHP设计模式介绍 第十一章 代理模式
PHP设计模式介绍 第十二章 装饰器模式
PHP设计模式介绍 第十三章 适配器模式