PHP 数据库读写操作的设计 (三)

数据库读取操作类的设计

虽然有了 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());
    }
}
?>

参考资料
《大话设计模式》程杰着 清华大学出版社

文章来源: PHP 数据库读写操作的设计 (三)

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:PHP 数据库读写操作的设计 (三)