PEAR:创建中间的数据库应用层的步骤
一、什么是DB类我们首先简单地了解一下DB类。DB类是PEAR中进行数据操作的几个类的集合,它的主要目的是提供一个统一的,抽象的数据接口,这个接口与后端的数据库是无关的。因此,如果你的应用程序使用这个通用的接口来进行数据库的操作,那么就能够平滑地切换到不同的数据库下面,如MYSQL,SQL,SYBASE等等。实际上,DB类希望能够起到简单的类似ODBC或者是PERL中的DBI的作用。说到这里,不得不提一下PHP中的另一个优秀的库:ADODB。ADODB也和DB一样,提供了一个抽象的中间层,而且ADODB所支持的后端数据库要比DB多(至少目前如此),不过ADODB没有直接使用PEAR的一些特性,只是吸取了PEAR的许多思想,包括DB,因此二者的使用方法有许多相似的地方。我不想评论二者孰优孰劣,大家可以根据个人的喜好来使用。
二、为什么要设计抽象的中间数据层
在详细讨论DB的使用之前,我们先讨论一下为什么要设计中间的数据层,因为这意味着你需要作出一些牺牲和让步,比如,你需要多写一些代码,有的局限于特定数据库的特性将无法直接使用。
我们回忆一下我们过去的做法,如何连接到MYSQL数据库?这的确是个小儿科的问题,下面的代码你一定很熟悉:
/**
* 连接到MYSQL数据库
*/
$host
= "localhost";
$user
= "root";
$passwd = "";
$persistent = 1;
if ($persisternt){
$conn = mysql_connect($host,$user,$passwd);
}else {
$conn = mysql_pconnect($host,$user,$passwd);
}
?>
好了,现在建立了数据库连接,我们可以使用它来进行数据库的操作,我们可能使用类似的代码:
function sql_exec($sql) {
global $db_Name;
$result = mysql_db_query($db_dbName,$sql);
if (!$result) {
echo mysql_errno(). ": ".mysql_error(). "$sql";
exit();
}
return $result;
}
$db_Name = "test";
$sql = "select * from users";
$result = sql_exec($sql);
while( $row = mysql_fetch_row($result) ){
echo "姓名:$row[0] 性别:$row[1] 年龄 $row[2]";
}
mysql_free_result($result);
?>
看起来很不错,是吗?你可能在你的代码里使用很多类似的代码片段。但是,不要太高兴,问题来了。假如,突然,你的数据库需要从MYSQL迁移到别的数据库平台,比如ORACLE,SYBASE。迁移的原因很多,也许是你的老板突发奇想,认为这样能卖个好价钱,或者是你的数据猛增,导致MYSQL的性能下降,总之,迁移是事在必行了。你怎么做,你也许会想,呵呵,这简单,把相关的函数替换一下不就行了。
听起来简单,但是……首先,连接数据库的函数要改,需要把mysql_connect和mysql_pconnect替换成OCILogon和OCIPLogon。mysql_errno和mysql_error()当然不能使用,你需要从OCIError()返回的数组中提取响应的信息。
这还不是太糟,最糟的是相关的mysql_fetch_row,mysql_fetch_array等语句遍布于你的许多代码函数和过程中,你需要逐一查找,分析,然后重新替换或者编写相应的ORACLE的版本。如果,你的数据库操作是集中在一个某一个模块或类中,这项工作还可以接受,否则,等于你重新阅读和修改了绝大部分的代码。即使这个不幸的人不是你,那么他也会暗地里诅咒你的;=)
以上,我们回忆了我们以前的做法,以及可能带来的不幸。那么,如果使用DB类来做类似的操作,应该是什么样的呢?下面是相应的DB版本代码:
include_once "DB.php";
/*
* 连接到数据库
*/
$db_host = "localhost";
$db_user = "root";
$db_passwd = "";
$db_dbName = "test";
$PersistentConnection = 1 ;
$db_type ="mysql";
$db_proto ="";
$db = DB::connect("$db_type://$db_user@$db_passwd:$db_host/$db_dbName",$db_options);
if( DB::isError($db) ){
die "无法连接数据库,错误原因:".DB::errorMessage($db);
}
function sql_exec($sql) {
global $db;
$result = $db->query($sql);
if (DB::isError($result)){
echo "发生数据库错误:".DB::errorMessage($result);
exit();
}
return $result;
}
/////////////////////////////////////////////
$sql = "select * from users";
$result = sql_exec($sql);
while( $row = $result->fetchRow() ){
echo "姓名:$row[0] 性别:$row[1] 年龄 $row[2]";
}
?>
除了连接数据库部分,其他的看起来只是有一些微小的变化,出错处理使用的是PEAR类似的方式(isError),实际上也是从PEAR继承来的。同样的情况,如果你要把数据库从mysql迁移到别的形式,这次假如说是PostegreSQL,一个LINUX中很优秀的数据库,你所做的只是改变一行代码:
$db_type ="mysql";
变成:
$db_type ="pgsql";
其他的,不用变动。怎么样,升级的感觉是不是很清爽呢,你可以用剩下的时间好好研读其余的代码,或者和我继续往下讨论DB的使用方法。
三、 DB的使用入门
DB类由3部分组成:
DB.php 这是前端接口,在DB类里提供了许多"静态"的公用方法,我们一般只需要INCLUDE_ONCE这个文件就可以了。
DB/common.php 这是后端数据库的通用抽象类,不同的数据库的后端类需要继承并实现这个类中定义的公用方法和属性,如果你的数据库不被支持,你可以自己编写一个支持类,这样,你的应用程序就可以迁移过来了。
DB/storage.php 这是一个辅助的工具,它可以把SQL查询做为对象返回,同时能够维护这些对象,在对象改变的时候,相应地更新数据库。
DB/ifx.php
mssql.php
Ms SQL Server支持类
oci8.php
Orcale 8i支持类
pgsql.php
PostegreSQL支持类
sybase.php Sybase支持类
ibase.php
ibase支持类
msql.php
mSQL 支持类
mysql.php
mysql支持类
odbc.php
odbc 支持类
这些是相应后端数据库的支持类了。相应具体的数据库的操作是由这些支持类来实现的。
下面,我们首先详细介绍DB.PHP中的一些"静态"方法:
connect()方法
这个方法是最重要的静态方法了,我们通过得到一个DB_COMMON对象,并且连接到相应的数据库。这个方法的原型如下:
function &connect($dsn, $options = false)
$dsn是数据源名称(data source name)的缩写,可以是字符串,或者是特定的数组形式。
一般来说,$dsn是一个字符串,它的格式如下:
phptype(dbsyntax)://username:password@protocol+hostspec/database
*
phptype:
php后端数据库的类型名称(如mysql, odbc 等等.)
*
dbsyntax: 数据库所使用的SQL语法标准,一般不用。
*
protocol: 使用的通讯协议。(如tcp, unix 等等.)
*
hostspec: 数据库所在的主机的描述。(形式是:主机名[:端口号])
*
database: 数据库的名称。
*
username: 登陆的用户名。
*
password: 登陆的密码。
对于DSN,常用的形式如下:
*
phptype://username:password@protocol+hostspec:110//usr/db_file.db
*
phptype://username:password@hostspec/database_name
*
phptype://username:password@hostspec
*
phptype://username@hostspec
*
phptype://hostspec/database
*
phptype://hostspec
*
phptype(dbsyntax)
*
phptype
对于省略的部分,将使用缺省值。
当然,$dsn也可以是一个数组,数组的形式如下:
$dsn = array(
'phptype'
=> 'mysql',
'dbsyntax' => '',
'protocol' => '',
'hostspec' => 'localhost',
'database