php adodb介绍
程序员文章站
2022-06-10 17:18:10
虽然 php 是建构 web 系统强有力的工具,但是 php 存取数据库的功能,一直未能标准化,每一种数据库,都使用另一种不同且不兼容的应用程序接口(api)。为了填补这个...
虽然 php 是建构 web 系统强有力的工具,但是 php 存取数据库的功能,一直未能标准化,每一种数据库,都使用另一种不同且不兼容的应用程序接口(api)。为了填补这个缺憾,因此才有 adodb 的出现。一旦存取数据库的接口予以标准化,就能隐藏各种数据库的差异,若欲转换至其它不同的数据库,将变得十分容易。
目前 adodb最新版本是v4.62,支持的数据库种类非常地多,例如:mysql, postgresql, interbase, informix, oracle, ms sql 7, foxpro, access, ado, sybase, db2 以及一般的 odbc (其中 postgresql、informix、sybase 的driver 是由*软件社群发展之后贡献出来的)。
使用 adodb 最大的优点之一是:不管后端数据库如何,存取数据库的方式都是一致的,开发设计人员不必为了某一套数据库,而必须再学习另一套不同的存取方法,这大大减轻开发人员的知识负担,过去的知识往后仍可继续使用,转移数据库平台时,程序代码也不必做太大的更动。
其实 adodb 这样的发展理念,并不是首创的,dbi 比 adodb 出现得更早,它提供 perl 存取数据库时,使用一致的 api 呼叫接口。相信用过 perl + dbi 的朋友,再来用 adodb 时,会有一种似曾相识的感觉。
另外,adodb 对用过 asp 的人而言,应该不陌生,这类朋友对 adodb 应该很容易接受。
adodb官方:http://adodb.sourceforge.net/
php可以用最少的精力以及最多的乐趣来建立动态的网站,要建立动态网站我们需要使用数据库来撷取登入账号信息、发布动态新闻、储存讨论区的文章。 就以使用最通用的 mysql 数据来说,你们公司已经完成了如此神奇的工作,让你们的网站比你们所能想象的还要出名。接着你们也发现mysql无法应付实际的工作量了,是该更换数据库 系统的时候了。
不幸地,在php中所有数据库的存取都有些细微的不同。与mysql连结你要使用 mysql_connect(),当你决定升级到 oracle 或 microsoft sql server 时,你必须分别改用 ocilogon() 或 mssql_connect()。更糟糕的是不同连结所使用的参数也都不一样,有的数据库说 po-tato(马铃薯的发音),别的数据库又说 pota-to(马铃薯的另一个发音),喔…..天啊。
我们不要放弃
当你需要确保你程序的可移植性的时候,一个叫做 adodb 的数据库封包链接库已经出现了。它提供了共通的应用程序接口来跟所有支持的数据库沟通,因此你无须放弃!
adodb是active data object database的缩写(很抱歉!玩计算机的有时候不是很有原创性)。adodb目前支持mysql、postgresql、oracle、 interbase、microsoft sql server、access、foxpro、sybase、odbc及ado,你可以从 http://php.weblogs.com/adodb下载 adodb。
mysql的例子
php中最通用的数据库是mysql,所以我想你会喜欢下面的程序代码,它连结到 localhost 的 mysql 服务器,数据库名称是 mydab,并且执行一个 sql 的 select 指令查询,查询结果会一列列地印出来。
$db = mysql_connect("localhost", "root", "password");
mysql_select_db("mydb",$db);
$result = mysql_query("select * from employees",$db);
if ($result === false) die("failed");
while ($fields = mysql_fetch_row($result)) {
for ($i=0, $max=sizeof($fields); $i < $max; $i++) {
print $fields[$i].' ';
}
print "<br>n";
}
上列的程序代码用颜色标出分段,第一段是连结的部分,第二段是执行sql指令,最后一段则是显示字段,while循环扫描结果的每一列,而for循环扫描到每列的字段。
接下来是以adodb的程序代码得到同样的结果:
include("adodb.inc.php");
$db = newadoconnection('mysql');
$db->connect("localhost", "root", "password", "mydb");
$result = $db->execute("select * from employees");
if ($result === false) die("failed");
while (!$result->eof) {
for ($i=0, $max=$result->fieldcount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->movenext();
print "<br>n";
}
现在改成指向oracle数据库,程序代码只要修改第二行成为 newadoconnection('oracle'),让我们看一下完整的程序代码...
与数据库连结
include("adodb.inc.php");
$db = newadoconnection('mysql');
$db->connect("localhost", "root", "password", "mydb");
连结的程序代码比起原来mysql的程序代码有老练一些,因为我们正是需要更老练些。在adodb我们使用对象导向的方法来管理多样数据库的复杂 性,我们用不同类(class)来控制不同数据库。假如你不熟悉对象导向程序设计,别担心!所有的复杂事情都隐藏在 newadoconnection() 函数之后。
为了节省内存,我们只加载与你所连结数据库相关的php程序代码,我们通过调用newadoconnection(databasedriver) 来完成这件事,合法的数据库驱动程序包含 mysql,mssql,oracle,oci8,postgres,sybase,vfp,access,ibase 以及许多其它的驱动程序。
接着我们通过调用 newadoconnection() 来从连结类别产生一个新的对象实体,最后我们使用 $db->connect() 来连结数据库。
执行sql指令
$result = $db->execute("select * from employees");
if ($result === false) die("failed");
直接传送sql指令到服务器,当成功执行之后,execute()将传回一个recordset对象,你可以如同上面所列来检查$result。
一个初学者容易混淆的议题是,在adodb有两种类型的对象,连结对象以及recordset对象,我们何时用这些对象呢?
连结对象($db)是负责连结数据库,格式化你的sql查询。而recordset对象($result)则是负责撷取结果并将响应数据规格化成文字或数组。
唯一我需要增加的事情是,adodb提供许多有用的函数来让insert及update指令更容易些,这点我们在进阶的章节会提到。
撷取资料
while (!$result->eof) {
for ($i=0, $max=$result->fieldcount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->movenext();
print "<br>n";
}
前面取得数据的范例很像从档案读数据,在每一行我们首先检查是否到了档案的结尾(eof),若还没到结尾,循环扫过每列中的字段,然后移到下一行(movenext)接着重复同样的事情。
$result->fields[]数组是由php数据库延伸系统所产生的,有些数据库延伸系统并不会以字段名称建立该数组的索引,要强迫以名称排序索引该数组,使用$adodb_fetch_mode的通用变量。
$adodb_fetch_mode = adodb_fetch_num;
$rs1 = $db->execute('select * from table');
$adodb_fetch_mode = adodb_fetch_assoc;
$rs2 = $db->execute('select * from table');
print_r($rs1->fields); // shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); // shows array(['col1']=>'v0',['col2'] =>'v1')
如同你所见的上面例子,两个recordset储存并使用不同的取用模式,当recordset由execute()产生后再设定$adodb_fetch_mode。
adoconnection
连结到数据库的对象,执行sql指令并且有一组工具函数来标准格式化sql指令,比如关联与日期格式等指令。
其它有用的函数
$recordset->move($pos)卷动目前的数据列,adodb支持整个数据库往前卷动,有一些数据库并不支持往后的卷动,这倒不会是个问题,因为你能够用暂存纪录到快取来仿真往后卷动。
$recordset->recordcount()传回sql指令存取到的纪录笔数,有些数据库会因为不支持而传回-1。
$recordset->getarray()以数组的方式传回结果。
rs2html($recordset)函数将传进的recordset转为html的表格格式。下例中以粗体字显示相关用法:
include('adodb.inc.php');
include('tohtml.inc.php'); /* includes the rs2html function */
$conn = &adonewconnection('mysql');
$conn->pconnect('localhost','userid','password','database');
$rs = $conn->execute('select * from table');
rs2html($rs); /* recordset to html table */
还有许多其它有用的函数列示在文件之中,可从下列网址查得 http://php.weblogs.com/adodb_manual
进阶题材
新增及更新
假设你要新增下列数据到数据库中。
id = 3
thedate=mktime(0,0,0,8,31,2001) /* 31st august 2001 */
note= sugar why don't we call it off
当你改用别的数据库,可能就没办法新增数据。
第一个问题是,每一个数据库各自有不同的内定日期格式,mysql使用 yyyy-mm-dd 格式,而其它数据库则有不同的内定格式,adodb提供dbdate()函数来转换不同数据库之间的日期内定格式。
次一个问题是单引号(don't)的表示法,在mysql可以直接使用单引号(don't),但在其它数据库如sybase、access、 microsoft sql server,则用两个单引号表示(don''t),qstr()函数可以解决此问题。
我们如何使用这些函数?就像这样:
$sql = "insert into table (id, thedate,note) values ("
. $id . ','
. $db->dbdate($thedate) .','
. $db->qstr($note).")";
$db->execute($sql);
adodb还有$connection->affected_rows()函数,传回受最后update或delete指令影响的数据列数, 及$recordset->insert_id()函数,传回最后因insert指令而自动产生的数据列编号,预先提醒大家,没有任何数据库有提供 这两个函数。
metatypes
你可以得到关于字段的更多信息,透过recordset的方法fetchfield($fieldoffset)传回对象的3个属性:name,type,max_length。
举例说明:
$recordset = $conn->execute("select adate from table");
$f0 = $recordset->fetchfield(0);
结果$f0->name的内容是'adata',$f0->type将是'date',假如max_length不知道,其内容将会是-1。
处理不同数据库的一个问题是,每一个数据库对于相同的数据型态会有不同的称呼,比如timestamp型态在某数据库中称为datetime,而另 一个数据库则称为time,所以adodb提供metatype($type,$max_length)函数来标准化下列的数据型态:
c: character and varchar types
x: text or long character (eg. more than 255 bytes wide).
b: blob or binary image
d: date
t: timestamp
l: logical (boolean)
i: integer
n: numeric (float, double, money)
在前面的例子中,
$recordset = $conn->execute("select adate from table");
$f0 = $recordset->fetchfield(0);
$type = $recordset->metatype($f0->type, $f0->max_length);
print $type; /* should print 'd' */
select指令的limit及top支持
adodb有个$connection->selectlimit($sql,$nrows,$offset)函数让你撷取 recordset的部分集合,这是采用microsoft产品中的select top用法,及postgresql与mysql中的select...limit用法的优点,即使原来的数据库并没有提供此用法,本函数也仿真提供该使 用方式。
快取支援
adodb允许你在你的档案系统中暂存recordset的数据,并且在$connection->cacheexecute($ secs2cache,$sql)及 $connection->cacheselectlimit($secs2cache,$sql,$nrows,$offset)等设定的时间间 隔到达之后,才真正去做数据库的查询以节省时间。
php4 session支持
adodb也支持php4 session handler,你可以存放你的session变量在数据库中,相关功能请参考 http://php.weblogs.com/adodb-sessions
鼓励商业使用
假如你计划写商用的php应用软件来销售,你也可以使用adodb,我们依据gpl来出版adodb,也就是说你可以合法地在商用应用软件中引用,并保有你程序代码的所有权。强烈地鼓励adodb的商业应用,我们自己内部也正以这个理由如此使用中。
目前 adodb最新版本是v4.62,支持的数据库种类非常地多,例如:mysql, postgresql, interbase, informix, oracle, ms sql 7, foxpro, access, ado, sybase, db2 以及一般的 odbc (其中 postgresql、informix、sybase 的driver 是由*软件社群发展之后贡献出来的)。
使用 adodb 最大的优点之一是:不管后端数据库如何,存取数据库的方式都是一致的,开发设计人员不必为了某一套数据库,而必须再学习另一套不同的存取方法,这大大减轻开发人员的知识负担,过去的知识往后仍可继续使用,转移数据库平台时,程序代码也不必做太大的更动。
其实 adodb 这样的发展理念,并不是首创的,dbi 比 adodb 出现得更早,它提供 perl 存取数据库时,使用一致的 api 呼叫接口。相信用过 perl + dbi 的朋友,再来用 adodb 时,会有一种似曾相识的感觉。
另外,adodb 对用过 asp 的人而言,应该不陌生,这类朋友对 adodb 应该很容易接受。
adodb官方:http://adodb.sourceforge.net/
php可以用最少的精力以及最多的乐趣来建立动态的网站,要建立动态网站我们需要使用数据库来撷取登入账号信息、发布动态新闻、储存讨论区的文章。 就以使用最通用的 mysql 数据来说,你们公司已经完成了如此神奇的工作,让你们的网站比你们所能想象的还要出名。接着你们也发现mysql无法应付实际的工作量了,是该更换数据库 系统的时候了。
不幸地,在php中所有数据库的存取都有些细微的不同。与mysql连结你要使用 mysql_connect(),当你决定升级到 oracle 或 microsoft sql server 时,你必须分别改用 ocilogon() 或 mssql_connect()。更糟糕的是不同连结所使用的参数也都不一样,有的数据库说 po-tato(马铃薯的发音),别的数据库又说 pota-to(马铃薯的另一个发音),喔…..天啊。
我们不要放弃
当你需要确保你程序的可移植性的时候,一个叫做 adodb 的数据库封包链接库已经出现了。它提供了共通的应用程序接口来跟所有支持的数据库沟通,因此你无须放弃!
adodb是active data object database的缩写(很抱歉!玩计算机的有时候不是很有原创性)。adodb目前支持mysql、postgresql、oracle、 interbase、microsoft sql server、access、foxpro、sybase、odbc及ado,你可以从 http://php.weblogs.com/adodb下载 adodb。
mysql的例子
php中最通用的数据库是mysql,所以我想你会喜欢下面的程序代码,它连结到 localhost 的 mysql 服务器,数据库名称是 mydab,并且执行一个 sql 的 select 指令查询,查询结果会一列列地印出来。
$db = mysql_connect("localhost", "root", "password");
mysql_select_db("mydb",$db);
$result = mysql_query("select * from employees",$db);
if ($result === false) die("failed");
while ($fields = mysql_fetch_row($result)) {
for ($i=0, $max=sizeof($fields); $i < $max; $i++) {
print $fields[$i].' ';
}
print "<br>n";
}
上列的程序代码用颜色标出分段,第一段是连结的部分,第二段是执行sql指令,最后一段则是显示字段,while循环扫描结果的每一列,而for循环扫描到每列的字段。
接下来是以adodb的程序代码得到同样的结果:
include("adodb.inc.php");
$db = newadoconnection('mysql');
$db->connect("localhost", "root", "password", "mydb");
$result = $db->execute("select * from employees");
if ($result === false) die("failed");
while (!$result->eof) {
for ($i=0, $max=$result->fieldcount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->movenext();
print "<br>n";
}
现在改成指向oracle数据库,程序代码只要修改第二行成为 newadoconnection('oracle'),让我们看一下完整的程序代码...
与数据库连结
include("adodb.inc.php");
$db = newadoconnection('mysql');
$db->connect("localhost", "root", "password", "mydb");
连结的程序代码比起原来mysql的程序代码有老练一些,因为我们正是需要更老练些。在adodb我们使用对象导向的方法来管理多样数据库的复杂 性,我们用不同类(class)来控制不同数据库。假如你不熟悉对象导向程序设计,别担心!所有的复杂事情都隐藏在 newadoconnection() 函数之后。
为了节省内存,我们只加载与你所连结数据库相关的php程序代码,我们通过调用newadoconnection(databasedriver) 来完成这件事,合法的数据库驱动程序包含 mysql,mssql,oracle,oci8,postgres,sybase,vfp,access,ibase 以及许多其它的驱动程序。
接着我们通过调用 newadoconnection() 来从连结类别产生一个新的对象实体,最后我们使用 $db->connect() 来连结数据库。
执行sql指令
$result = $db->execute("select * from employees");
if ($result === false) die("failed");
直接传送sql指令到服务器,当成功执行之后,execute()将传回一个recordset对象,你可以如同上面所列来检查$result。
一个初学者容易混淆的议题是,在adodb有两种类型的对象,连结对象以及recordset对象,我们何时用这些对象呢?
连结对象($db)是负责连结数据库,格式化你的sql查询。而recordset对象($result)则是负责撷取结果并将响应数据规格化成文字或数组。
唯一我需要增加的事情是,adodb提供许多有用的函数来让insert及update指令更容易些,这点我们在进阶的章节会提到。
撷取资料
while (!$result->eof) {
for ($i=0, $max=$result->fieldcount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->movenext();
print "<br>n";
}
前面取得数据的范例很像从档案读数据,在每一行我们首先检查是否到了档案的结尾(eof),若还没到结尾,循环扫过每列中的字段,然后移到下一行(movenext)接着重复同样的事情。
$result->fields[]数组是由php数据库延伸系统所产生的,有些数据库延伸系统并不会以字段名称建立该数组的索引,要强迫以名称排序索引该数组,使用$adodb_fetch_mode的通用变量。
$adodb_fetch_mode = adodb_fetch_num;
$rs1 = $db->execute('select * from table');
$adodb_fetch_mode = adodb_fetch_assoc;
$rs2 = $db->execute('select * from table');
print_r($rs1->fields); // shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); // shows array(['col1']=>'v0',['col2'] =>'v1')
如同你所见的上面例子,两个recordset储存并使用不同的取用模式,当recordset由execute()产生后再设定$adodb_fetch_mode。
adoconnection
连结到数据库的对象,执行sql指令并且有一组工具函数来标准格式化sql指令,比如关联与日期格式等指令。
其它有用的函数
$recordset->move($pos)卷动目前的数据列,adodb支持整个数据库往前卷动,有一些数据库并不支持往后的卷动,这倒不会是个问题,因为你能够用暂存纪录到快取来仿真往后卷动。
$recordset->recordcount()传回sql指令存取到的纪录笔数,有些数据库会因为不支持而传回-1。
$recordset->getarray()以数组的方式传回结果。
rs2html($recordset)函数将传进的recordset转为html的表格格式。下例中以粗体字显示相关用法:
include('adodb.inc.php');
include('tohtml.inc.php'); /* includes the rs2html function */
$conn = &adonewconnection('mysql');
$conn->pconnect('localhost','userid','password','database');
$rs = $conn->execute('select * from table');
rs2html($rs); /* recordset to html table */
还有许多其它有用的函数列示在文件之中,可从下列网址查得 http://php.weblogs.com/adodb_manual
进阶题材
新增及更新
假设你要新增下列数据到数据库中。
id = 3
thedate=mktime(0,0,0,8,31,2001) /* 31st august 2001 */
note= sugar why don't we call it off
当你改用别的数据库,可能就没办法新增数据。
第一个问题是,每一个数据库各自有不同的内定日期格式,mysql使用 yyyy-mm-dd 格式,而其它数据库则有不同的内定格式,adodb提供dbdate()函数来转换不同数据库之间的日期内定格式。
次一个问题是单引号(don't)的表示法,在mysql可以直接使用单引号(don't),但在其它数据库如sybase、access、 microsoft sql server,则用两个单引号表示(don''t),qstr()函数可以解决此问题。
我们如何使用这些函数?就像这样:
$sql = "insert into table (id, thedate,note) values ("
. $id . ','
. $db->dbdate($thedate) .','
. $db->qstr($note).")";
$db->execute($sql);
adodb还有$connection->affected_rows()函数,传回受最后update或delete指令影响的数据列数, 及$recordset->insert_id()函数,传回最后因insert指令而自动产生的数据列编号,预先提醒大家,没有任何数据库有提供 这两个函数。
metatypes
你可以得到关于字段的更多信息,透过recordset的方法fetchfield($fieldoffset)传回对象的3个属性:name,type,max_length。
举例说明:
$recordset = $conn->execute("select adate from table");
$f0 = $recordset->fetchfield(0);
结果$f0->name的内容是'adata',$f0->type将是'date',假如max_length不知道,其内容将会是-1。
处理不同数据库的一个问题是,每一个数据库对于相同的数据型态会有不同的称呼,比如timestamp型态在某数据库中称为datetime,而另 一个数据库则称为time,所以adodb提供metatype($type,$max_length)函数来标准化下列的数据型态:
c: character and varchar types
x: text or long character (eg. more than 255 bytes wide).
b: blob or binary image
d: date
t: timestamp
l: logical (boolean)
i: integer
n: numeric (float, double, money)
在前面的例子中,
$recordset = $conn->execute("select adate from table");
$f0 = $recordset->fetchfield(0);
$type = $recordset->metatype($f0->type, $f0->max_length);
print $type; /* should print 'd' */
select指令的limit及top支持
adodb有个$connection->selectlimit($sql,$nrows,$offset)函数让你撷取 recordset的部分集合,这是采用microsoft产品中的select top用法,及postgresql与mysql中的select...limit用法的优点,即使原来的数据库并没有提供此用法,本函数也仿真提供该使 用方式。
快取支援
adodb允许你在你的档案系统中暂存recordset的数据,并且在$connection->cacheexecute($ secs2cache,$sql)及 $connection->cacheselectlimit($secs2cache,$sql,$nrows,$offset)等设定的时间间 隔到达之后,才真正去做数据库的查询以节省时间。
php4 session支持
adodb也支持php4 session handler,你可以存放你的session变量在数据库中,相关功能请参考 http://php.weblogs.com/adodb-sessions
鼓励商业使用
假如你计划写商用的php应用软件来销售,你也可以使用adodb,我们依据gpl来出版adodb,也就是说你可以合法地在商用应用软件中引用,并保有你程序代码的所有权。强烈地鼓励adodb的商业应用,我们自己内部也正以这个理由如此使用中。
下一篇: 麦片能放蜂蜜吗?想加一点其实很好吃的