【IT168 文档】本文将揭示如何使用DAO设计模式生成可以完成各种常见MySQL数据库操作的PHP类。
数据访问对象(DAO)为数据库提供了一个抽象接口,使得开发人员无需了解数据库模式的详细信息就可以访问常见数据库操作——实际上,数据访问对象实现了应用程序的低级别的数据访问逻辑与高级别的业务逻辑的分离。这种分离是非常重要的,因为它使得这两种重要的应用程序层可以彼此相对独立,从而使我们可以经常地对它们进行单独扩展。使用DAO后,发生变化的商业逻辑可以使用相同的DAO接口,同时对逻辑的修改不会影响DAO客户端——只要该接口的实现是适当的。
用于PHP和MySQL的DAO Generator可以自动为MySQL数据库创建DAO类。本文中,我们将介绍如何:
- 安装用于PHP和MySQL的DAO Generator
- 生成一个使用给定数据库(bookstore)的DAO工件
- 使用DAO Generator工具及其工厂类创建一个应用程序
- 创建一个生成多个SQL操作的事务
- 为生成的类添加一个定制的DAO函数
一、用于PHP和MySQL的DAO Generator
通常情况下,我们会使用某种特定的语言来给具体的目标数据库生成各种类。例如,我们可以使用DAO Generator给PHP语言和MySQL数据库生成PHP类,以便利用这些类来查询和更新使用了DAO设计模式的MySQL数据库。这个工具的安装和使用都很简单,但是要想高效的使用它,就需要对DAO机制有一点点的了解。
您可以下载用于PHP和MySQL的DAO Generator,地址为http://www.phpdao.com/。若要安装它,可以按照以下步骤操作:
1.下载压缩文档phpdao-1.7.zip。
2. 将下载的文件解压到htdocs目录。
3. 通过在templates/class/dao/sql/ConnectionProperty.class.php文件中指定数据库属性来为现有数据库设置一个连接。
4. 运行generate.php脚本。
5. 该工具将生成的类加入到新建的、名为generated的文件夹中。
下面的图 1展示了用于PHP和MySQL的DAO Generator的体系结构。
图 1. DAO Generator的体系结构:该图展示了用于PHP和MySQL的的DAO Generator的体系结构和数据流程
二、DAO类入门
下面简要介绍各种重要的DAO类:
- ConnectionFactory类:这个类与数据库密切相关。这个工厂类用于连接数据库,或者说打开一个数据库的连接。 连接数据库时,这个类要用到getConnection方法,该方法需要三个参数,分别对应于数据库名称、用户名和口令。这些参数将按照POJO的风格映射到类ConnectionProperty中。 static public function getConnection() {
$conn = mysql_connect(ConnectionProperty::getHost(),
ConnectionProperty::getUser(),
ConnectionProperty::getPassword());
mysql_select_db(ConnectionProperty::getDatabase());
if(!$conn){
throw new Exception('could not connect to database');
}
return $conn;
} - Connection类:这个类代表的是单个数据库连接,该连接是通过Connection构造函数引自ConnectionFactory类的。 这个类还负责关闭连接以及执行SQL查询。public function Connection() {
$this->connection = ConnectionFactory::getConnection();
} - Transaction类:这个类封装了一组对数据库进行事务性操作的函数。此外,这个类还提供了事务数组,这些事务是通过助手类ArrayList来提供的,其中ArrayList可以通过PHP数组来模拟一个集合。这些事务将使用Connection类所提供的连接。此外,Transaction类的getCurrentTransaction函数提供了对当前事务的访问能力。
- QueryExecutor类:这个类为我们提供了执行SQL语句的各种函数。实际上,这些函数都实现了CRUD语法。函数execute可以执行所有的SELECT语句,而函数executeUpdate则执行UPDATE、DELETE和INSERT语句: public static function execute($sqlQuery){
$transaction = Transaction::getCurrentTransaction();
if(!$transaction){
$connection = new Connection();
}else{
$connection = $transaction->getConnection();
}
$query = $sqlQuery->getQuery();
$result = $connection->executeQuery($query);
if(!$result){
throw new Exception(mysql_error());
}
$i=0;
$tab = array();
while ($row = mysql_fetch_array($result)){
$tab[$i++] = $row;
}
mysql_free_result($result);
if(!$transaction){
$connection->close();
}
return $tab;
}
public static function executeUpdate($sqlQuery){
$transaction = Transaction::getCurrentTransaction();
if(!$transaction){
$connection = new Connection();
}else{
$connection = $transaction->getConnection();
}
$query = $sqlQuery->getQuery();
$result = $connection->executeQuery($query);
if(!$result){
throw new Exception(mysql_error());
}
return mysql_affected_rows();
} - {databasename}MySqlDAO类:这是由DAO Generator创建的一个类,它提供了一组特定于某种数据库的DAO函数。生成的类位于generated/class/mysql文件夹内,并且它们的名称是由数据库名称和后缀MySqlDAO结合而成的。在本文的后面,我们将介绍如何生成和使用这个类。
注意,类QueryExecutor和类{databasename}MySqlDAO使用了一个名为SqlQuery的助手类,它封装有表示和存储SQL语句的各种函数。
为了便于读者深入理解,我们下面将通过一个实例加以阐述。
三、生成DAO工件
下面我们说明一个使用名为bookstore的数据库的DAO工件的生成进程。该数据库含有一个表,表的名称为books,其结构如图2所示。
图 2. 表Books的结构:该图展示了数据库bookstore中的表Books中的一些样本数据及其结构
为了创建如图2所示的表,可以执行如下所示的SQL语句:
(id int not null auto_increment primary key,
title varchar(50),
author varchar(50),
yearofpublication int,
publisher varchar(50),
price int);
生成该DAO工件之前,需要使用以下INSERT语句向表books中填入五条记录:
"Edgar Allan Poe",1849,"The Literature Page",256);
insert into books values(2,"The Ballad of Reading Gaol",
"Oscar Wilde",1898,"The Literature Page",475);
insert into books values(3,"The Sonnets",
"Edgar Allan Poe",1602,"The Literature Page",300);
insert into books values(4,"Winnetow",
"Karl May",1956,"The truth",123);
insert into books values(5,"JBoss Tools 3",
"Anghel Leonard",2009,"Packt",569);
创建并填充好有关数据库和表之后,我们就可以执行DAO Generator来创建DAO工件了。若要运行该生成器,需要执行下列操作:
⒈ 在ConnectionProperty类中设置连接属性:host、user、password和database。
2. 运行generated.php脚本。
3. 我们将得到如下所示的输出结果:
varchar(50)
varchar(50)
varchar(50)
varchar(50)
int(11)
int(11)
varchar(50)
varchar(50)
int(11)
int(11)
generated/class/mysql/BooksMySqlDAO.class.php
varchar(50)
varchar(50)
int(11)
varchar(50)
int(11)
generated/class/dao/BooksDAO.class.php
generated/include_dao.php
generated/class/dao/DAOFactory.class.php
4. 输出结果中的最后三行是生成的类的名称,这些类被放入phpdao-1.7目录的新建子目录中。
为应用程序生成的这三个类都用到表books。第一个类位于generated/class/dto/Books.php文件中,它定义了一个表示表books的对象:
/**
* Object represents table 'books'
*
* @author: http://phpdao.com
* @date: 2009-08-10 22:50
*/
class Books{
var $id;
var $title;
var $author;
var $yearofpublication;
var $publisher;
var $price;
}
?>
第二个类位于generated/class/dao/BooksDAO.php文件中(请参阅清单1),它是一个接口,定义了针对表books的各种各样的操作。
第三个类,也是最后一个类位于/class/mysql/BooksMySqlDAO.php文件中,它实现了前面的接口。您可以在相应的文件夹中看到这个类,由于它很长,所以这里就不列出来了。
四、使用事务
本节展示如何使用PHP和MySQL的DAO Generator来创建一个事务。这里将要使用PHP和MySQL的DAO Generator来创建example.php脚本并将其放到generated文件夹中,其中generated文件夹中存放了所有的DAO文件。在本例中,我们的事务将生成两个SQL语句,即SELECT和DELETE语句:
//包含所有的DAO文件
require_once('include_dao.php');
$transaction = new Transaction();
//将表清空
//DAOFactory::getBooksDAO()->clean();
$transaction->rollback();
//启动一个新的事务
$transaction = new Transaction();
echo '****** Query All the books table ******'.'<br/>';
$arr = DAOFactory::getBooksDAO()->queryAll();
for($i=0;$i<count($arr);$i++){
$row = $arr[$i];
echo $row->id.' '.$row->title.' '.$row->author.' '.
$row->yearofpublication.' '.$row->publisher.' '.
$row->price.'<br/><br/>';
}
echo '****** Deleting the third row ******'.'<br/>';
$rowDeleted = DAOFactory::getBooksDAO()->delete(3);
echo 'rows deleted ='.$rowDeleted.'<br/><br/>';
echo '****** Loading the fifth row ******'.'<br/>';
$art = DAOFactory::getBooksDAO()->load(5);
echo 'Price for the fifth record book is = '.$art->price.'<br/><br/>';
echo '****** Printing all rows order by title ******'.'<br/>';
$article = DAOFactory::getBooksDAO()->queryAllOrderBy('title');
for($i=0;$i<count($article);$i++){
$row = $article[$i];
echo $row->id.' '.$row->title.' '.$row->author.' '.
$row->yearofpublication.' '.$row->publisher.' '.
$row->price.'<br/><br/>';
}
//提交事务
$transaction->commit();
?>
当运行该例子时,将输出下列内容:
1 Annabel Lee Edgar Allan Poe 1849 The Literature Page 256
2 The Ballad of Reading Gaol Oscar Wilde 1898 The Literature Page 45
3 The Sonnets Edgar Allan Poe 1602 The Literature Page 300
4 Winnetow Karl May 1956 The truth 123
5 JBoos Tools 3 Anghel Leonard 2009 Packt 569
****** Deleting the third row ******
rows deleted =1
****** Loading the fifth row ******
Price for the fifth record book is = 569
****** Printing all rows order by title ******
1 Annabel Lee Edgar Allan Poe 1849 The Literature Page 256
5 JBoos Tools 3 Anghel Leonard 2009 Packt 569
2 The Ballad of Reading Gaol Oscar Wilde 1898 The Literature Page 45
4 Winnetow Karl May 1956 The truth 123
五、新添加DAO函数
本节展示如何创建一个新的DAO函数,该函数用于打印出版日期介于1850到2009之间的所有记录。将其添加到BooksMySQLDAO.class.php中所有现有的query函数的后面:
$sql = "SELECT * FROM books WHERE yearofpublication".
" BETWEEN '1850' AND '2009'";
$sqlQuery = new SqlQuery($sql);
return $this->getList($sqlQuery);
}
您也可以使用example.php页面来调用前面的函数,并打印yearofpublication介于1850到2009之间的记录:
'1850' and '2009'******".'<br/>';
$arr = DAOFactory::getBooksDAO()->queryByYear();
for($i=0;$i<count($arr);$i++){
$row = $arr[$i];
echo $row->id.' '.$row->title.' '.$row->author.' '.
$row->yearofpublication.' '.$row->publisher.' '
.$row->price.'<br/><br/>';
输出结果为:
2 The Ballad of Reading Gaol Oscar Wilde 1898 The Literature Page 45
4 Winnetow Karl May 1956 The truth 123
5 JBoss Tools 3 Anghel Leonard 2009 Packt 569
六、小结
我们已经学习了DAO机制的工作原理,包括使用工厂类模式生成指定数据库(bookstore)的DAO工件的过程,使用DAO generator工具及其工厂类创建应用程序的过程,创建一个数据库bookstore的事务过程,以及为生成的{databasename}MySqlDAO 类添加新的DAO函数的方法。当然,我们可以手工方式编程实现所有这些功能,但是最好将这些重复性的工作自动化,因为这样不仅能够降低出错率,而且还能节约宝贵的时间。