《PHP设计模式介绍》第十四章 动态记录模式(4)_PHP教程
推荐:《PHP设计模式介绍》第十三章 适配器模式接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题。程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库的发展和进化。我孩子的无数玩具中有一个简要地描
然而,因为书签类的构造函数调用了静态方法DB:conn()来获取数据库连接,要注入模拟连接到其中就很困难了。这儿有一些可能的实现方法:增加一个方法来改变$this->conn,增加一个可选参数到每一个方法中,或是增加一个参数到构造函数中。让我们选用最后一种方法:给Bookmark的构造函数增加一个可选的参数。
class Bookmark { // ... public function __construct($id=false, $conn=false) { $this->conn = ($conn) ? $conn : DB::conn(); // ... } } |
现在,新的Bookmark依然能正常工作,但新的Bookmark(1, $connection)用参数中的$connection对象代替正常的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!!!!’); $link = new Bookmark(1,$conn); $this->assertErrorPattern(‘/exploded/i’); $conn->tally(); } |
动态记录实例ID
在前面的例子中,大多数属性都是公共的,然而,书签ID是受保护的,以其值被免意外更改(如果其值被意外更改,当你想更新书签数据的时候问题就出现了)。因为$ID是受保护的,因此增加一个辅助方法来获取其值。
class Bookmark { protected $id; //... public function getId() { return $this->id; } } |
怎样来测试它呢?
class ActiveRecordTestCase extends UnitTestCase { // ... function testGetId() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); // second bookmark, id=2 $link = $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $this->assertEqual(2, $link->getId()); } } |
如上,add()方法生并成保存数据,并通过getid()方法获取生成数据的ID值并验证其是相匹配的。
但是,如果你想用别的条件来验证所生成的数据而不仅仅是用书签的ID,或是你如何确保从数据库中返回的ID是正确的?用select语句根据给定的属性条件取得数据,并验证返回行的ID值是一个好的技术方法。
class ActiveRecordTestCase extends UnitTestCase { // ... function testGetId() { $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); // second bookmark, id=2 $link = $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $this->assertEqual(2, $link->getId()); $alt_test = $this->conn->getOne( “select id from bookmark where url = ‘http://phparch.com’”); $this->assertEqual(2, $alt_test); //alternatively $this->assertEqual($link->getId(), $alt_test); } } |
注意到这个试验类似于你用手工执行一个SQL查询来验证数据是否正确插入到书签表中。通过本次实验所实现代码,还能用于你后续实验中来验证数据的正确性,而不是仅仅简单的去执行它。
记录搜索
现在,我们已能实现保存书签对象到数据库,并且能根据书签ID从数据库中获取相应数据来重建书签对象。但是当ID值并不知道(通常情况也是这样)时会发生什么?或是你想通过如部分名称或是URL等相关值来搜索数据库,则更常见的解决方法是增加一个”finder”方法。
例如,你也许想使用findByUrl()方法查找与给定参数相类似的书签,下面的实验则能实现上述的要求。
class ActiveRecordTestCase extends UnitTestCase { // ... function testFindByUrl() { $this->add(‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $this->add(‘http://php.net’, ‘PHP’, ‘PHP Language Homepage’, ‘php’); $this->add(‘http://phparch.com’, ‘php|architect’, ‘php|arch site’, ‘php’); $result = Bookmark::findByUrl(‘php’); $this->assertIsA($result, ‘array’); $this->assertEqual(2, count($result)); $this->assertEqual(2, $result[0]->getId()); $this->assertEqual(‘php|architect’, $result[1]->name); } } |
该实验生成一些数据,查找URL中包含有“PHP”字样的行,并校检返回的书签对象数组中的字符。FindByUrl()之所以是一个静态方法,是因为你有可能在没的书签对象实例化的情况下进行该操作。(当然你也能将“查找“方法放到每一个对象中,但目前 “查找”方法仍然是书签类中的一个方法。)
分享:《PHP设计模式介绍》第十二章 装饰器模式若你从事过面向对象的php开发,即使很短的时间或者仅仅通过本书了解了一些,你会知道,你可以 通过继承改变或者增加一个类的功能,这是所有面向对象语言的一个基本特性。如果已经存在的一个php
- 相关链接:
- 教程说明:
PHP教程-《PHP设计模式介绍》第十四章 动态记录模式(4)。