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

本文介绍了一种使用模板方法设计数据库操作类的方法,通过抽象基类InfoDAL简化了数据库的读写操作,特别是针对大量相似的SQL插入语句进行了优化。

数据库读取操作类的设计

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

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

内容概要:本文系统研究了基于CNN-SVM的卷积神经网络与支持向量机融合的数据分预测方法,聚焦其在工业故障识别中的应用,提供了完整的Matlab代码实现。通过CNN提取输入数据的深层空间特征,再由SVM进行高精度分,充分发挥两者优势,有效提升了故障识别的准确性、鲁棒性与泛化能力。该方法特别适用于处理电力系统、机械设备等领域的高维、非线性、强噪声监测数据,在变压器故障诊断、轴承缺陷识别等场景中具有重要应用价值。文档还整合了机器学习、深度学习、图像处理、路径规划、电力系统优化等多个前沿科研方向的技术资源,配套大量Matlab/Simulink仿真案例与Python代码,全面支持科研复现与工程实践。; 适合人群:具备一定编程基础,熟练掌握Matlab或Python语言,从事电气工程、自动化、人工智能、机械故障诊断等相关领域研究的研发人员及高校研究生; 使用场景及目标:① 实现工业设备的状态监测与多别故障分;② 深入理解CNN与SVM融合模型的设计原理与工程实现细节;③ 借助所提供的丰富算法案例开展科研复现、模型优化与系统仿真验证; 阅读建议:建议按照文档目录结构系统化学习,结合百度网盘提供的完整代码资源进行动手实践,重点关注CNN特征提取层与SVM分器之间的数据接口设计与参数调优策略,同时可延伸学习文中涉及的其他智能算法及其在电力系统、信号处理等领域的交叉应用,全面提升科研创新能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值