
数据库读取操作类的设计
虽然有了 DBHelper 类可以简化数据库读写操作的工作,然而一堆的 SQL 命令也是令人够烦的,例如:
INSERT INTO table1 (‘栏位1’, ‘栏位2’, ‘栏位3’, … ) VALUES ( 值1, 值2, 值3, …)
INSERT INTO table2 (‘栏位1’, ‘栏位2’, ‘栏位3’, … ) VALUES ( 值1, 值2, 值3, …)
整个系统中会到处充斥着这些类似的程序代码,有没有什么样的方法可以用来简化这些工作?
利用模板方法 (Template Method)设计数据读取类 InfoDAL
以上面新增数据为例,只有数据表名称、栏位名称、栏位值三个地方不同,所以只要有办法取得数据表名称及所有栏位名称、栏位值,就可以用一个共同的方法来操作新增的动作了。看下面代码:
abstract class InfoDAL
{
private $aDBHelper;
public function __construct() {
$this->aDBHelper = DBFactory::Create();
}
public function __destruct() {
$this->aDBHelper = null;
}
abstract public function getTableName(); // 抽象函式,继承者必须改写。
public function Insert($myInfo) {
$buf1 = '';
$buf2 = '';
foreach($myInfo-> getProperties() as $Key => $Value){
if( $buf1 == '' ) {
$buf1 = $Key;
$buf2 = ":$Key";
} else {
$buf1 = $buf1.",$Key";
$buf2 = $buf2.",:$Key";
}
}
$szTable = $this->getTableName();
$SQL = "INSERT INTO $szTable ($buf1) VALUES($buf2)";
$this->aDBHelper->Transaction($SQL, $myInfo->getProperties());
}
}
InfoDAL 是一个数据库读取的基础类,它需要 DBHelper 的帮忙,但不需要继承它,透过 DBFactory 去取得就行。任何继承自 InfoDAL 的类都必须去实作一个 getTableName(),传回它对应的数据表名称,例如:
class CategoryDAL extends InfoDAL
{
public function getTableName()
{
return "category";
}
}
InfoDAL::Insert() 方法需要一个MyInfo 类的参数,利用其getProperties()可以取得所有的属性名称及其值。简单的程序代码,要弄懂应该不难。
在实作上,针对每一个数据表(例如:category)设计一个数据类(CategoryInfo)继承 MyInfo,然后相对的设计一个读取类(CategoryDAL) 继承 InfoDAL,那么新增的工作就可以简化成如下:
$aDAL = new CategoryDAL();
$aObj = new CategoryInfo();
$aObj->ParentNo = $ParentNo;
$aObj->ID = $ID;
$aObj->Title = $Title;
$aObj->SortKey = $SortKey;
$aDAL->Insert($aObj);
结语
MyInfo的getProperties()设计是针对 InfoDAL 而产生的,MyInfo 及 InfoDAL 是我经过许多种的尝试而底定下来的,在开发网站系统中,它们是随影而行。
程杰的《大话设计模式》中对模板模式有这么一句话:
『所有重复的程序代码都应该要上升到父类别去,而不是让每个子类别都去重复。』
最后附上完整的 InfoDAL 程序代码,有些设计是为了因应我个人的状况,增删随缘。
<?php
require_once('DBFactory.php');
abstract class InfoDAL
{
private $aDBHelper;
//----------------------------------------------------
public function __construct() {
$this->aDBHelper = DBFactory::create();
}
//----------------------------------------------------
public function __destruct() {
$this->aDBHelper = null;
}
//----------------------------------------------------
// 抽象函式,继承者需重写。
abstract public function newObject();
abstract public function getTableName();
abstract public function getPrimaryKey();
//----------------------------------------------------
public function deleteByKey($aList) {
$SQL = 'DELETE FROM '.$this->getTableName().
' WHERE '.$this->getPrimaryKey().
' IN ('.$aList.')';
$this->aDBHelper->execute($SQL, NULL);
}
//----------------------------------------------------
public function exec($SQL, $aAry=null) {
$this->aDBHelper->execute($SQL, $aAry);
}
//----------------------------------------------------
public function getLastKey() {
$SQL = 'SELECT '.$this->getPrimaryKey().
' FROM '.$this->getTableName().
' ORDER BY '.$this->getPrimaryKey().' DESC';
if( $res = $this->query($SQL) )
return $res[0];
else
return 0;
}
//----------------------------------------------------
public function getOne($SQL, $aAry=NULL) {
$result = $this->aDBHelper->getOne($SQL, $aAry);
$aInfo = $this->newObject();
if( $result ) {
foreach($result as $key=>$value) {
if( $value == '0000-00-00')
$aInfo->$key = '';
else
$aInfo->$key = $value;
}
}
return $aInfo;
}
//----------------------------------------------------
public function getOneByKey( $key ) {
$SQL = 'SELECT * FROM '.$this->getTableName().
' WHERE '.$this->getPrimaryKey().' = :Key';
$aAry = array(':Key' => $key);
return $this->getOne($SQL, $aAry);
}
//----------------------------------------------------
public function insert($aObj) {
$buf1 = '';
$buf2 = '';
foreach( $aObj->getProperties() as $Key => $Value) {
if( $buf1 == '' ) {
$buf1 = $Key;
$buf2 = ":$Key";
} else {
$buf1 = $buf1.",$Key";
$buf2 = $buf2.",:$Key";
}
}
$szTable = $this->getTableName();
$SQL = "INSERT INTO $szTable ($buf1) VALUES($buf2)";
$this->aDBHelper->execute($SQL, $aObj->getProperties());
}
//----------------------------------------------------
// 不以物件的方式傳回資料。
public function query($SQL, $aAry=NULL, $bAll=false) {
return $this->aDBHelper->query($SQL, $aAry, $bAll);
}
//----------------------------------------------------
public function save( $aObj ) {
if( $aObj->isEmpty() )
$this->insert($aObj);
else
$this->update($aObj);
}
//----------------------------------------------------
public function update( $aObj ) {
$buf = '';
foreach($aObj->getProperties() as $Key=>$Value) {
if($buf =='')
$buf = "$Key=:$Key";
else
$buf = $buf.",$Key=:$Key";
}
$szTable = $this->getTableName();
$szPrimaryKey = $this->getPrimaryKey();
$SQL = "UPDATE $szTable SET $buf".
" WHERE $szPrimaryKey=:$szPrimaryKey";
$this->aDBHelper->execute($SQL, $aObj->getProperties());
}
}
?>
参考资料
《大话设计模式》程杰着 清华大学出版社
人吐槽 | 人点赞 |
发表评论