到目前為止,您所看到的這些設計模式大大提高了代碼的可讀性與可維護性。然而,在WEB應用設計與開發中一個基本的需求與挑戰:數據庫應用,這些設計模式都沒有涉及到。本章與接下來的兩章—表數據網關與表數據映射,提供了三種設計模式使您能更好的組織你的應用程序與數據庫進行交互。
問題
大多數WEB應用將信息持續保存在數據庫中。有將數據庫操作抽象化,以達到簡化表數據存取和對業務邏輯的集成存取方法嗎?
解決方案
理論上,動態記錄模式是最簡化的有關數據庫的設計模式。動態記錄模式包含了如何在類中直接實現與數據庫交互的相關知識。
動態記錄模式在程序代碼與數據庫結構之間產生了一種很高的結合度,在一些相對簡單的應用環境中,就能比采用別的復雜方案更容易解決這種因結合所產生的一些固有問題。動態記錄模式也能滿足許多初級的數據庫項目。只有當復雜性增加而難以用動態記錄模式處理時,你才有必要使用表數據網關模式(參見15章),或是數據地圖模式(參見16章)或是別的數據庫設計模式
企業級應用架構模式
根據Martin Fowler’s的著作《企業級應用架構模式》,所謂企業級應用就是與別的應用集成化,包含了重要的業務邏輯(或如應用需求所呈現的非邏輯的東西),并且具有許多并發存取和保存從各種接口取得的數據。有趣的是,web應用正好具備了上述多個特點,這正好能解釋為什么Martin Fowler’s的著作能引起PHP程序員的強烈反響。
PHP數據對象
PDO是一個高性能的數據庫通道接口(并非數據庫抽象)。PDO是一個由C語言構成的本地驅動包,因此其速度是很快的。PDO為所有的PDO驅動提供了申明,增強了腳本使用庫時的安全性。
樣本代碼
任何對數據庫連接的討論都依賴于對數據庫系統與對數據庫訪問層的選擇。本章與隨后兩章都使用MYSQL(http://www.mysql.com/)這個流行的開源數據庫及ADOdb (http://adodb.sf.net/)作為數據庫訪問層。我將ADOdb作為我自己工作室的標準是因為它優異的性能,且抽象了Oracle OCI接口,并提供了統一的訪問PostgreSQL, Sybase, MySQL和其它數據庫的接口,而成為了易于使用的PHP API,讓你專注于程序與業務邏輯的處理。
放心的替換你的自己的數據庫與訪問層,因為這里提出的許多概念也適合于別的解決方案。
在研究t動態記錄模式之前,讓我們從基本的數據庫連接開始。有一個集中的,簡單的方式去指定連接參數(主機名,用戶名,密碼,數據庫)并建立一個數據庫連接對象是很理想的。一個單一模式對象(參見第四章)就非常適合了。
這是一個DB類,其conn()方法返回一個單一模式的ADOConnection類的實例。
| // PHP5 require_once ‘adodb/adodb.inc.php’; class DB { //static class, we do not need a constructor private function __construct() {} public static function conn() { static $conn; if (!$conn) { $conn = adoNewConnection(‘mysql’); $conn->connect(‘localhost’, ‘username’, ‘passwd’, ‘database’); $conn->setFetchMode(ADODB_FETCH_ASSOC); } return $conn; } } |
DB類允許你設定數據庫的類型與連接參數。第一行代碼將ADOdb庫包含進來(你可能需要根據你的實際環境來調整路徑);因為沒有必要每次都實例化DB,所以DB的構造函數是私有的; 行$conn->setFetchMode(ADODB_FETCH_ASSOC)設定對象返回的記錄集是以(字段名=>值)形式的關聯數組。與數據庫打交道中采用關聯數組是非常重要的經驗習慣,這樣您的代碼就不會受到因SQL語句中字段排序而產生的影響。
作為示例程序,讓我們建立一個Active Record對象來維護一個超鏈接表。以下是一個在MySQL數據庫中建立這個超鏈接表的SQL。
| define(‘BOOKMARK_TABLE_DDL’, <<<EOS CREATE TABLE `bookmark` ( `id` INT NOT NULL AUTO_INCREMENT , `url` VARCHAR( 255 ) NOT NULL , `name` VARCHAR( 255 ) NOT NULL , `description` MEDIUMTEXT, `tag` VARCHAR( 50 ) , `created` DATETIME NOT NULL , `updated` DATETIME NOT NULL , PRIMARY KEY ( `id` ) ) EOS ); |
實驗的獨立性
各個實驗間應是相互獨立的;否則,僅僅是運行了某一個實驗就會影響到后續實驗的結果。
為了避免這些都基于同一數據庫的實驗間相互干擾,最好是在每個測試開始前刪除并重建相關表。以下簡單的實驗為后續實驗提供了一種標準的setup方法。
以下代碼演示如何在每個實驗開始前重置你的數據庫:
| class ActiveRecordTestCase extends UnitTestCase { protected $conn; function __construct($name=’’) { $this->UnitTestCase($name); $this->conn = DB::conn(); } function setup() { $this->conn->execute(‘drop table bookmark’); $this->conn->execute(BOOKMARK_TABLE_DDL); } } |
這段代碼用一個標準的ADOConnection對象來給$conn的屬性賦值,并且使用了Connection的execute()方法來執行SQL刪除與重建表的操作。因為這些代碼在一個名為setup()的方法中,使得每一個實驗都能在一個新的數據庫環境中工作。
新聞熱點
疑難解答