|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
会有很多高手的鼓励,新手的支持,慢慢你劲头就十足,有更多的信心和兴趣去学。oracle|对象|数据 一位新 PHP 数据对象 (PDO) 数据笼统层的原始开辟人员为您扼要引见该笼统层,重点讲述与 Oracle 一同运转的情形。
需求 PHP:5.0
需求其他:Oracle 8 或更高版本客户端库
下载用于 Oracle 的 PDO (Windows):php_pdo.dll, php_pdo_oci.dll
下载用于 Oracle 的 PDO (Unix):pdo, pdo_oci
PDO 简介
PHP 次要是由意愿者完成的项目;虽然有多数一些固定的“中心”开辟人员,然而咱们没有一团体在全职受薪的开辟 PHP。除此以外,咱们分离位于世界分歧中央,您可以想象临时开辟的调和任务是多么坚苦。因而,PHP 次要是基于突发奇想的团体短时间需求来开展的,其缘由也多种多样,有的是实验,有的则是由于“今天有活要交”。虽然如许凡是每步城市改良 PHP,但从久远来看则是缺少完全性 - 数据库扩大就是一个主要的例子。
在各类分歧的数据扩大(oci、mysql、postgresql、mssql 等)之间基本没有真实的分歧性,乃至在某些情形下,在这些扩大外部也没有真实的分歧性。几近一切这些扩大都在利用与基本数据库 API 严密相连的分歧代码完成着不异品种的义务。并且由于咱们(PHP 中心开辟人员和扩大开辟人员)的人手十分无限,因而这就形成了代码加倍难以保护,从而为 PHP 带来了很大的成绩。
因为 PHP 愈来愈受接待其实不断胜利,因而次要 PHP 数据库扩大的保护者们列入了在德国举办的 LinuxTag 2003 大会,在会上咱们互换了对 PHP 远景的意见。在会商 PHP 开展的随机性时,咱们肯定了在 PHP 中停止数据库会见的一些方针:
・供应一种轻型、明晰、便利的 API
・一致各类分歧 RDBMS 库的共有特征,但不扫除更初级的特征。
・经由过程 PHP 剧本供应可选的较大水平的笼统/兼容性。
咱们之所以提出了这类 PHP 数据对象 (PDO) 的概念,是由于咱们但愿经由过程采取 Zend Engine 2(PHP 5 的中心)先辈的面向对象特征取得该 API 的一些更优异的功能。
PHP 中的数据笼统层概念一点都算不上新;在 Google 中查询“PHP database abstraction”会找到大约 83,200 个婚配项。它几近是很多 PHP 开辟人员朝思暮想的,而其发生则局部归因于咱们不完全的 API。假如您已经测验考试过利用第三方笼统层来完成任何真正主要的任务,凡是会发明这些笼统层关于手头的任务来讲设计的功效过于壮大了 - 或体现为在利用前需求停止大批进修,或体现为接口速度迟缓,参数需求经由多层剧本函数挪用才干抵达数据库自有的 API;凡是是存在上述两种表象。
为何这些笼统层会存在这类成绩?这些笼统层老是在试图完成太多的义务,乃至多是不成能的义务。咱们决意以适用为方针,仅将一些最多见的数据库 API 特征作为咱们的基本,并使得 PDO 驱动法式可以将它们特定于产物的特征表露为惯例扩大函数。
为何利用 PDO?
听过有关数据库笼统扩大讹传的大多半人会立即对 PDO 的扩大方面发生困惑 - 咱们是不是要剖析 SQL,将其转换为响应的后端方言呢?咱们若何处置特征 X 或特征 Y,等等。因而,当您传闻咱们在 PDO 中基本不必为此而担心时能够会大吃一惊;咱们不但愿使一切内容都完整一致,由于要使得这类一致成为能够,只能是将本人限制在最低的通用尺度。
假如 PDO 不是一个全体的笼统层,那还有甚么其余缘由值得您思索利用它吗?
・功能。PDO 从一入手下手就吸收了现无数据库扩大胜利和掉败的经历经验。由于 PDO 的代码是全新的,所以咱们无机会从头入手下手设计功能,以使用 PHP 5 的最新特征。
・才能。PDO 旨在将罕见的数据库功效作为基本供应,同时供应关于 RDBMS 共同功效的便利会见。
・复杂。PDO 旨在使您可以轻松利用数据库。API 不会强行参与您的代码,同时会清晰地标明每一个函数挪用的进程。
・运转时可扩大。PDO 扩大是模块化的,使您可以在运转时为您的数据库后端加载驱动法式,而不用从头编译或从头装置全部 PHP 法式。例如,PDO_OCI 扩大会替换 PDO 扩大完成 Oracle 数据库 API。还有一些用于 MySQL、PostgreSQL、ODBC 和 Firebird 的驱动法式,更多的驱动法式尚在开辟。
您能够想懂得 PDO 与其他经常使用的笼统层的对照情形,例如 PEAR DB 或 ADODB。不管在 API 方面仍是在功能方面,PDO 都比其他罕见笼统层要轻型,然而触及到在各个数据库后端之间供应一致性方面,则不如那些笼统层,例如用于处置大批可移植性成绩的 PEAR MDB 2 笼统层。
在哪里可以取得 PDO?
PDO 是经由过程 PECL(发音为“pee-kle”,欧洲言语作风),即 PHP 扩大库供应的。假如您在运转 Linux 盘算机,请依照上面的申明停止设置;稍后是在 Windows 上装置的具体信息。
请注重,PDO 及其驱动法式以后处于“alpha”形态;这就意味着咱们会集理包管没有严重缺点,然而该法式包功效其实不完美 - 咱们还要添加良多功效。固然咱们勉励您测试该法式包,然而其实不保举在现阶段将其用于临盆。
Unix/Linux 装置
假如您之前还没有测验考试过 PHP 5,则请花一点工夫来通读一下“旧事”和各类声明。在 UNIX 盘算机上,您能够要装置或晋级 libxml2;假如没有 libxml2,“pear”法式保证理东西就没法运转,您装置 PDO 时就会碰到良多坚苦。获得 PHP 5,并将其编译和装置。确保指定的前缀不是 /usr/local/,如许它就不会与 PHP 4 装置产生抵触了:
% ./configure --prefix=/usr/local/php5 --with-zlib [此处指定其他选项]
% make install
如今您就能够利用“pear”东西获得并装置 PDO 和用于 PDO 的 Oracle 驱动法式了。由于 PDO 以后标志为 alpha,所以默许情形下 pear 东西不会下载该法式包。在该法式包称号前面添加后缀“-alpha”,告诉该 pear 东西可以装置 alpha 版本: % PATH="/usr/local/php5/bin:$PATH"
% pear install PDO-alpha
您需求告诉 PHP 从公用于 PHP 5 的 php.ini 文件加载 PDO 驱动法式。假如您利用的前缀与我利用的一样,PHP 则会在 /usr/local/php5/lib/php.ini 中查找 php.ini 文件。向该文件中添加以下行:
extension=pdo.so
如今您需求获得数据库特定的驱动法式;关于 Oracle,此特定法式称为 PDO_OCI。在 shell 中,键入:
% pear install PDO_OCI-alpha
此驱动法式也需求从 php.ini 文件加载;将下行添加到后面添加的那行以后:
extension=pdo_oci.so
如今反省一下,确保它可以运转:
% php -m
在模块列表中,您应当会看到 PDO 和 PDO_OCI。
防火墙碍事了?
假如您位于防火墙的前面,则在利用 pear 装置法式获得法式包时能够会碰到一些成绩。假如产生这类情形,则可以依照以下申明手动下载并装置这些法式包:
% wget http://pecl.php.net/get/PDO
% pear install PDO-0.1.1.tgz
[ 将 extension=pdo.so 添加到 php.ini ]
% wget http://pecl.php.net/get/PDO_OCI
% pear install PDO_OCI-0.1.tgz
[ 将 extension=pdo_oci.so 添加到 php.ini ]
在上述两种情形下,都需求起首挪用“pear install”(后跟下载的真正法式包);上述示例中的版本号在本文编写之时是最新的,但跟着开辟的持续停止会产生变更。
Windows 装置
假如您正在运转 Windows,则请依照以下申明履行:
・从 http://www.php.net/downloads.php#v5 获得 PHP 5,将其解紧缩到 C:\php5。
・从 http://snaps.php.net/win32/PECL_5_0/php_pdo.dll 和
http://snaps.php.net/win32/PECL_5_0/php_pdo_oci.dll 分离获得 PDO
和 PDO_OCI,将其放入 C:\php5\ext。或,您可以从 PHP 5 下载页上列出的
“用于 PHP 5.0.0 的 PECL 模块纠合”zip 文件中找到一切这些 PDO 驱动法式,
和一切 PECL 法式包的一切 Windows 版本。
・编纂 C:\php5\php.ini 文件,并添加以下内容:
extension=php_pdo.dll
extension=php_pdo_oci.dll
编纂 php.ini 文件时,有一点很主要,即要在任何其他 PDO 驱动法式之前先加载 PDO 扩大,不然就不克不及准确初始化(在这类情形下会失足)。
假如在 Windows 目次中有一个 PHP 4 的全局 php.ini 文件,则能够会碰到成绩。最好的处理办法是,挪动该 php.ini 文件,使其与 PHP 4 SAPI 位于不异的文件夹中,以隔离 PHP 4 装置;例如,将其挪动到与 php4apache.dll 不异的文件夹中。请注重,PHP 5 法式中并不是一切文档都是最新的;保举的装置进程如下面所述 - 如 install.txt 文件所声明的,请勿将任何 DLL 复制到 windows 文件夹或 system 文件夹中 - 任何内容都是自包括的。假如您运转的是 apache,而且碰到没法加载 DLL 的毛病,则反省一下是不是将 C:\php5 添加到了 PATH 中。别的,还要注重 PHP 5 的 CGI 版本如今的称号为 php-cgi.exe。
毗连 PDO
起首创立 PDO 类的一个实例,将其用作数据库句柄。利用哪一个基本驱动法式其实不主要;您总要利用 PDO 类名。机关函数的第一个参数为数据源称号 (DSN),第二个参数为用户名,第三个参数为该用户名的口令。DSN 的 PDO 定名常规为 PDO 驱动法式的称号,前面一个冒号,再前面是可选的驱动法式特定的信息。在咱们的示例中,会加载 OCI 驱动法式但不指定任何其他信息;如许会利用默许的数据库。关于其他驱动法式,如 ODBC 驱动法式,第一个冒号前面的一切内容都将被用作 ODBC DSN。MySQL 驱动法式会一样以分歧的体例注释它的 DSN。
假如没法加载该驱动法式,或产生了毗连掉败,则会抛出一个 PDOException,以便您可以决意若何最好地处置该毛病。
<?php
try {
$dbh = new PDO("OCI:", "scott", "tiger");
} catch (PDOException $e) {
echo "Failed to obtain database handle " .$e->getMessage();
}
?>
在毗连字符串中,您可以指定两个可选参数;第一个是数据库称号,第二个是字符集;这些参数与可选的第三个和第四个参数绝对应,后两个参数您能够在 oci8 扩大函数 ociconnect() 或 ociplogon() 中利用过。要利用特定的字符集毗连一个特定的数据库,则可以履行以下操作:
<?php
try {
$dbh = new PDO("OCI:dbname=accounts;charset=UTF-8", "scott", "tiger");
} catch (PDOException $e) {
echo "Failed to obtain database handle " .$e->getMessage();
}
?>
省略 try..catch 掌握布局并没有裨益。假如在使用法式的较初级别没有界说异常处置,则在没法创立数据库毗连的情形下,该剧本会终止。
毗连办理
今朝,PDO 完整没有履行本人的任何毗连办理,因而每一个“新 PDO”挪用城市创立一个新的数据库毗连。该毗连在 $dbh 变量越界时,或当您为其指定 NULL 值时会被释放。
<?php
try {
$dbh = new PDO("OCI:dbname=accounts;charset=UTF-8", "scott", "tiger");
} catch (PDOException $e) {
echo "Failed to obtain database handle " .$e->getMessage();
exit;
}
// 在此处对数据库履行一些操作
// ...
// 如今完成,释放该毗连
$dbh = null;
?>
企图在不久的未来为 PDO 增添毗连缓存功效;就以后的 oci8 扩大而言,会重用与现有办事器的毗连,而且在这些毗连中,还会重用闲置的登录。当在缓存毗连形式中运转时,如下面的代码段所示释放 $dbh 时会将该登录标志为可由其他毗连重用。
假如您利用 ODBC 驱动法式会见 Oracle,则能够会很乐意地注重到,默许情形下 PDO_ODBC 驱动法式撑持 ODBC 毗连池。
利用 PDO
懂得一个编程 API 的最好体例就是利用它,因而咱们来看一下附带的这个演示,以懂得若何停止批次更新(代码以下)。
<?php
// Create a PDO database handle object
// the 'oci:' string specifies that the OCI driver should be used
// you could use 'oci:dbname=name' to specify the database name.
// The second and third parameters are the username and password respectively
$dbh = new PDO('oci:', 'scott', 'tiger');
// Create a test table to hold the data from credits.csv
$dbh->exec("
CREATE TABLE CREDITS (
extension varchar(255),
name varchar(255)
)");
// start a transaction
$dbh->beginTransaction();
// prepare to insert a large quantitiy of data
$stmt = $dbh->prepare("INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)");
// bind the inputs to php variables; specify that the data will be strings
// with a maximum length of 64 characters
$stmt->bindParam(':extension', $extension, PDO_PARAM_STR, 64);
$stmt->bindParam(':name', $name, PDO_PARAM_STR, 64);
// Open the .csv file for import
$fp = fopen('credits.csv', 'r');
while (!feof($fp)) {
list($extension, $name) = fgetcsv($fp, 1024);
$stmt->execute();
}
fclose($fp);
// Commit the changes
$dbh->commit();
?>
既然咱们已胜利毗连到了 Oracle,那末如今就能够创立一个表来保留一些数据了。关于此示例,咱们利用一些 PHP 扩大及其作者,并将这些内容输出一个数据库中。数据库句柄对象的 exec() 办法可用来收回不会前往了局集的疾速一次性查询,因而咱们在这里利用该办法来收回 CREATE TABLE 查询。
为了使得示例更天然,我从 PHP 源代码中抽取了扩大及其作者的信息,并将其存储到了一个 CSV 文件中(请拜见“相干附件:credits.csv”)。这就代表一个罕见情况:从 CSV 文件批次导入数据。在咱们的示例中,咱们充实使用了 Oracle 的预处置语句和绑定参数,以取得一个高效的数据导入剧本。在讲述该示例之前,有需要懂得一下 PDO 处置事务的体例。
PDO 中的事务处置
Oracle 具有一个敏感的默许操作形式:当您停止毗连时,将会位于一个隐式事务处置中,在提交事务之前个中的更改不会完整失效。除事务处置的尺度长处(原子性、分歧性、隔离性、可耐久性 - ACID)以外,数据库办事器在履行每次更新以后还不需求从头构建索引和其他外部布局;它可以延迟到提交以后停止。如许会减速代码的履行。Oracle 这点的确很好。
但不幸的是,并不是每一个数据库供给商都撑持事务处置,而且由于 PDO 旨在以一种绝对可移植的体例撑持这些事务处置,所以它默许情形下以主动提交形式运转。启用主动提交形式后,数据库驱动法式会隐式提交每一个胜利的更新。当您挪用 $dbh->beginTransaction() 时,就会恳求封闭主动提交,直到挪用 $dbh->commit() 或 $dbh->rollBack() 才会从头启用,详细取决于您的代码是如何编写的。假如基本驱动法式不撑持事务处置,则会抛出一个 PDOException。
假如产生了成绩而且 PHP 失足,您的剧本将加入而且事务处于待批形态;或您封闭数据库句柄时,PDO 会主动针对任何待批的事务挪用 $dbh->rollBack()。此行动会削减向数据库中提交能够不决义或已破坏数据的能够性,这是用于处置已保持事务的尺度语义。
预处置语句、存储进程
PDO 撑持利用 Oracle 款式定名的占位符语法将变量帮定到 SQL 中的预处置语句(与 oci8 扩大中的 ocibindbyname() 相似)。PDO 还为其他数据库(如 ODBC)供应了定名占位符摹拟,乃至可觉得生来就不撑持该概念的数据库(如 MySQL)摹拟预处置语句和绑定参数。这是 PHP 向前迈进的积极一步,由于如许可使开辟人员可以用 PHP 编写“企业级”的数据库使用法式,而不用出格存眷数据库平台的才能。
利用 PDO 预处置语句十分复杂,挪用数据库句柄的 prepare() 办法便可。它会前往一个语句句柄对象,然后您可使用该对象来绑定参数和履行语句。在此示例中,咱们将要界说两个定名占位符,“:extension”和“:name”,这两个占位符分离与 .CSV 文件中的 PHP 扩大称号和个中一个作者的姓名绝对应。
$stmt = $dbh->prepare("INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)");
预处置了语句以后,咱们利用 bindParam() 办法来将这些定名参数分离与 PHP 变量称号“$extension”和“$name”相干联(这与 ocibindbyname() 相似)。咱们还会告诉 Oracle,这些数据将要格局化为字符串,最大长度为 64 个字符。
$stmt->bindParam(':extension', $extension, PDO_PARAM_STR, 64);
$stmt->bindParam(':name', $name, PDO_PARAM_STR, 64);
咱们如今即筹办好拔出数据了 - 咱们只需求翻开该 CSV 文件,并从中获得数据便可。经由过程利用 fopen() 和 fgetcsv() 函数可以相当复杂地完成此操作。然后,咱们可使用 PHP list() 机关函数直接将 CSV 的列指定给变量“$extension”和“$name”。由于这些变量已绑定到了语句中,所以咱们如今要做的只是挪用该语句对象的 execute() 办法使其履行拔出。这类体例既便利又快捷 - 在事务处置时每一个迭代轮回只要两行。抵达文件尾时,咱们就能够当即利用数据库句柄的 commit() 办法来提交这些更改了。
假如您只是要传递输出参数,而且有很多如许的参数要传递,那末您会感觉上面所示的快捷体例语法十分有匡助;此语法使您可以省去对 $stmt->bindParam() 的挪用。
$stmt = $dbh->prepare("INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)");
$stmt->execute(array(':extension' => $extension, ':name' => $name));
您还可使用 bindParam 来为存储进程设置输出/输入参数;语法是完整不异的,只是查询有所分歧。上面的代码演示若何挪用一个名为“sp_add_item”的存储进程;其目标是要针对输出设置 $item_name,然后该存储进程将在前往时更新 $error_code。
$stmt = $dbh->prepare("begin sp_add_item(:item_name, :error_code); end");
$stmt->bindParam(':item_name', $item_name, PDO_PARAM_STR, 12);
$stmt->bindParam(':error_code', $error_code, PDO_PARAM_STR, 12);
$stmt->execute();
抓取数据
利用 PDO 抓取数据与停止拔出或更新类似,只是您履行完查询以后,将要反复挪用 fetch() 办法来获得了局集的下一行。停止获得的最复杂情形以下所示,值得注重的一点是,您还可以将参数绑定到查询,以掌握如 WHERE 子句如许的内容;履行此操作的语法与咱们已看到的 bindParam() 代码完整不异。
$stmt = $dbh->prepare("SELECT extension, name from CREDITS");
if ($stmt->execute()) {
while ($row = stmt->fetch()) {
print_r($row);
}
}
PDO 撑持一些分歧的抓取战略,这些战略在便利性和功能方面有所不同;经由过程将以下选项之一指定为 fetch() 办法的参数,您可以更改其前往值以顺应您的语法:
・PDO_FETCH_NUM - 每一个行抓取前往一个依照各位置索引的数组,而且以 0 为基数(第一列是第 0 个元素)。
while ($row = $stmt->fetch(PDO_FETCH_NUM)) {
printf("Extension %s, by %s<br>", $row[0], $row[1]);
}
・PDO_FETCH_ASSOC - 每一个行抓取依据行集中的列名,前往一个按列名索引的数组。
while ($row = $stmt->fetch(PDO_FETCH_ASSOC)) {
echo "Extension $row[EXTENSION] by $row[NAME]<br>";
}
・PDO_FETCH_BOTH - 每一个行抓取前往一个既依照各位置又依照列名索引的数组。也就是上述两种情形的直接组合。假如没有指定抓取形式,则该形式为默许形式。 ・PDO_FETCH_OBJ - 每一个行抓取前往一个匿名对象,其属性名与列名对应。
while ($row = $stmt->fetch(PDO_FETCH_ASSOC)) {
echo "Extension {$row->EXTENSION} by {$row->NAME}<br>";
}
・PDO_FETCH_LAZY - 每一个行抓取前往一个援用语句对象的重载对象。这“看起来”仿佛是 PDO_FETCH_OBJ 和 PDO_FETCH_BOTH 的组合,只是只要当您在剧本中会见 PHP 变量时才创立这些变量。
・PDO_FETCH_BOUND - 抓取每行,前往 TRUE。在利用绑定输入列时这类体例十分有效,它可以免创立不需求的任何数组或对象。(请拜见上面的示例)。
不管您利用哪一种抓取战略,当没有其他行可抓取时,fetch() 办法将会前往 FALSE。
如今我要讲述一些技能,假如您需求最初再调剂一下剧本功能的话,这些技能能够会对您有所匡助。但先给你一个忠言:要像回避瘟疫一样防止不成熟的优化。您应当老是首选最明晰、可保护性最好的处理计划。请记住,在一个典范的 Web 使用法式中,您不克不及权衡各类抓取形式间的区分,除非剧本要处置良多行。我再反复一遍:抓取形式间的功能区分十分小 - 请利用最合适您代码的形式。
请记住,利用 PDO_FETCH_NUM 的花消最小,由于会见列数据只是一个复杂的数值查询。PDO_FETCH_OBJ 使您可以利用 OO 语法将数据集的列作为对象的属性来会见,然而每一个属性会见都触及一个附加的散列查询,使得利用它的花消根基上与 PDO_FETCH_ASSOC 不异。每一个如许的形式城市复制整行,从而占用稍多的内存。
良多数据库驱动法式城市代表您事后抓取并缓存必定数目的行。PHP 每次会见个中一个如许行中的列时,它都需求将其复制到本人的公用内存区域中。假如您的查询触及良多行,而只需求基于某种庞杂的逻辑会见给定行的特定列,则您会发明 PDO_FETCH_LAZY 是一种防止利用良多内存的有效办法,由于它只要在您会见给定列时才复制该列。利用此体例时要注重,从某个给定语句为每一个 fetch() 抓取的“惰性对象”是每次迭代时利用的统一对象(以削减每次创立/烧毁它的开支)。这就暗示着您不克不及只是复杂地存储该对象用于今后的对照,由于它依然会援用该语句确当前行 - 您需求手动复制所需求的局部。
最初一种形式为 PDO_FETCH_BOUND,该形式会告诉 PDO 您已将一切列绑定到了 PHP 变量,而且除要它在抵达行集的末尾时告诉您外不需求它履行其余任何操作。绑定输入列在概念上与绑定输出参数类似,只是绑定输入列可以用于一切数据库驱动法式。您可以将 PHP 变量绑定到定名列,PDO 将在每次挪用 execute() 时对其停止更新。此手艺可用来剃去了局集中每列、每行的一些虚拟机械操作码(这类代码速度比原生码要慢)。这类手艺的弱点在于,能够会使您的代码难以跟踪(也称为 WTF 系数较高),您利用变量称号时需求倍加当心。上面的代码申明了绑定输入列的利用。请注重,您不用指定 PDO_FETCH_BOUND 便可利用 $stmt->bindColumn();PDO_FETCH_BOUND 只是一个关于您懂得只能利用绑定值的情形的一种优化。
$stmt = $dbh->prepare("SELECT extension, name from CREDITS");
if ($stmt->execute()) {
$stmt->bindColumn('EXTENSION', $extension);
$stmt->bindColumn('NAME', $name);
while ($stmt->fetch(PDO_FETCH_BOUND)) {
echo "Extension:$extension, Author:$name\n";
}
}
可移植性
辨别巨细写的列
PDO 旨在令利用可移植 SQL 的剧本运转优秀、可移植。本文中说起的一切查询(挪用存储进程除外)在利用任何 PDO 驱动法式时其运转功能应当不异 - 包含一切绑定输出变量和绑定输入列。
但有一个转换成绩 - 当您利用 PDO_FETCH_ASSOC 抓取数据时,分歧的驱动法式会以分歧的体例前往列名 - 某些会将列名转化为大写,某些转换为小写,某些则会使其呈查询中指定的款式。这关于 PHP 剧本来讲是一个潜伏的成绩,由于数组键辨别巨细写。PDO 供应了一个兼容性属性来匡助标准剧本的了局。上面的小代码段是下面 PDO_FETCH_BOUND 示例的可移植版本,由于 setAttribute() 办法挪用会指点 PDO 将抓取前往的列名全体转换为大写:
$dbh = new PDO('OCI:', 'scott', 'tiger');
$dbh->setAttribute(PDO_ATTR_CASE, PDO_CASE_UPPER);
stmt = $dbh->prepare("SELECT extension, name from CREDITS");
if ($stmt->execute()) {
$stmt->bindColumn('EXTENSION', $extension);
$stmt->bindColumn('NAME', $name);
while ($stmt->fetch(PDO_FETCH_BOUND)) {
echo "Extension:$extension, Author:$name\n";
}
}
除 PDO_CASE_UPPER 以外,还有 PDO_CASE_LOWER(它会将列名转换为小写)和 PDO_CASE_NATURAL(它是默许选项:使列坚持数据库驱动法式前往的模式)。
毛病和毛病处置
可移植剧本的另外一个困难是处置从各类数据库处置法式前往的各类分歧的毛病动静;某些数据库关于法式化处置毛病的撑持才能很差,而其他一些数据库则具有十分丰厚的毛病代码。只需可行,PDO 将为您的剧本供应一个一致的毛病代码,从而使您不用为应对可移植性的这个方面所累。固然,PDO 还会为驱动法式供应原生毛病代码和毛病动静,以防您需求用它来停止诊断,或毛病代码映照不完全。
另外一个困扰 PHP 数据库扩大的分歧性成绩是毛病处置战略的分歧性:某些扩大会前往的毛病代码需求您手动抓取毛病字符串,而其他一些扩大则只是收回 PHP 正告。PDO 答应您从以下三种分歧的毛病处置战略当选择一种:
・PDO_ERRMODE_SILENT
这是默许形式;它只是利用语句和数据库句柄对象的 errorCode() 和 errorInfo() 办法为您设置要反省的毛病代码。
if (!$dbh->exec($sql)) {
echo $dbh->errorCode() ."<BR>";
$info = $dbh->errorInfo();
// $info[0] == $dbh->errorCode() 一致的毛病代码
// $info[1] 是驱动法式特定的毛病代码
// $info[2] 是驱动法式特定的毛病字符串
}
・PDO_ERRMODE_WARNING
除设置毛病代码以外,PDO 还会收回 PHP 正告,您可使用惯例的 PHP 毛病处置法式捕捉该正告,并集中使用您筹办好用于使用法式的任何毛病处置/纪录战略,或只是使该毛病显示在阅读器中(在外部测试过程当中十分有效)。
・PDO_ERRMODE_EXCEPTION
除设置毛病代码以外,PDO 还会抛出一个 PDOException,并将其属性设置为包括该毛病代码和信息。然后,您可以在代码的较初级别捕捉该异常,利用全局异常处置法式捕捉该异常,或不合错误其停止处置而终止剧本(此时将回滚任何未决的事务)。
try {
$dbh->exec($sql);
} catch (PDOException $e) {
// 显示正告动静
print $e->getMessage();
$info = $e->errorInfo;
// $info[0] == $e->code; unified error code
// $info[1] 是驱动法式特定的毛病代码
// $info[2] 是驱动法式特定的毛病字符串
}
请注重,与正告或异常比拟,静默形式针对运转时毛病利用的资本起码,然而为了取得该速度,您就义了一些复杂性,而变得有一点庞杂。
一致毛病代码表以后包含以下常量: PDO_ERR_NONE、PDO_ERR_CANT_MAP、PDO_ERR_SYNTAX、PDO_ERR_CONSTRAINT、PDO_ERR_NOT_FOUND、PDO_ERR_ALREADY_EXISTS、PDO_ERR_NOT_IMPLEMENTED、PDO_ERR_MISMATCH、PDO_ERR_TRUNCATED、PDO_ERR_DISCONNECTED。
这些常量所代表的意思字面便可推知,然而 PDO_ERR_CANT_MAP 代码除外;这是一个 PDO 特定的代码,也就是说它没法将驱动法式特定的代码映照到一致的毛病代码,因而您应当查询 errorInfo() 办法前往的驱动法式特定代码来取得更多信息。
数据类型
PDO 在某种水平上类型不成知,因而它喜好将数据暗示为字符串,而不是将其转换为整数或双精度类型。此时您能够对此有些利诱,然而缘由十分复杂:字符串类型是最准确的类型,在 PHP 中具有最普遍的使用局限;过早地将数据转换为整数或双精度类型能够会招致截断或舍入毛病。经由过程将数据以字符串抽出,PDO 为您供应了一些剧本掌握,您可使用通俗的 PHP 类型转换东西(如数学运算过程当中的转换和隐式)来掌握若何停止转换和什么时候停止转换。
NULL
假如了局集中的某列包括一个 NULL 值,PDO 则会将其映照为 PHP null 值。Oracle 在将数据前往 PDO 时会将空字符串转换为 NULL,然而 PHP 撑持的任何其他数据库都不会如许处置,从而招致了可移植性成绩。PDO 供应了一个驱动法式级属性 PDO_ATTR_ORACLE_NULLS,该属性会为其他数据驱动法式摹拟此行动:
$dbh = new PDO('OCI:', 'scott', 'tiger'); $dbh->setAttribute(PDO_ATTR_ORACLE_NULLS, true); // 如今从此 $dbh 翻开的任何语句中的 // 空字符串都将被转换为 NULL POD 的近况和将来
PDO 如今仍相当不成熟,然而会疾速成熟起来。在编写本文之时,我在本文中提到的任何内容都可以经由过程 PDO_OCI 驱动法式合用于 Oracle 8 或更高版本(在 Oracle 8.0 和 9.2 上测试过)。
已企图增添以下次要特征,在不久将可使用:
1.利用 PHP 流的 LOB 撑持。 利用绑定参数,您可以将任何流资本(如文件、套接字、HTTP 资本、紧缩/挑选的流)作为输出或输入参数传递到在 LOB 上运转的查询中。与之类似,类型为 LOB 的输入参数将体现为 PHP 流,因而您可使用 fread()、fwrite()、fseek() 和其他流函数来会见这些参数。此时,在 PDO 中基本没有 LOB 撑持。
2.耐久性毗连弛缓存的预处置语句。 耐久性毗连使您可以防止在每一个页面射中时翻开和封闭数据库办事器毗连。缓存的预处置语句又行进了一步,它使您可以耐久坚持查询的预处置版本和数据库句柄。
3.游标。 今朝,PDO 只供应前向只读游标,然而未来会供应可转动游标(需求基本驱动法式撑持)、REF-CURSOR、利用游标停止定位更新,和可更新转动游标。
咱们但愿在 PHP 5.1 中默许启用 PHP 扩大(距此方针尚远),然而在此之前,咱们但愿能让 PDO 在 PHP 5.0 宣布时不乱运转,然而咱们平常任务中的压力稍稍稽延了这些任务。同时,经由过程 PECL 宣布 PDO 使咱们可以在收到成绩呈报时做出回应,并依据分歧于 PHP 5.0 宣布工夫表的工夫表宣布修复版本,因而您在 PHP 5.1 宣布前便可利用 PDO。
咱们需求您的反应
假如您试用了 PDO,而且发明了成绩,请务必利用咱们的毛病跟踪软件将其呈报给咱们。假如您利用的是 Oracle 驱动法式,则请利用此页:
http://pecl.php.net/bugs/report.php?package=PDO_OCI
假如您利用的是其他驱动法式,则请用其称号交换该 URL 中 PDO_OCI。
假如您利用 PDO 时碰到成绩,或针对某些特征存在疑问,或具有特征恳求,请接洽 pecl-dev@lists.php.net。假如您情愿,固然还可以直接接洽我 (wez@php.net),然而请注重,我天天城市收到大批有关 PHP 的电子邮件;您能够会发明假如起首与后面的邮件列表接洽会更快失掉回答。
关于作者
Wez Furlong 是 Brain Room Ltd. 的手艺总监,他在该公司不仅利用 PHP 用于 Web 开辟,还将其用作 Linux 和 Windows 使用法式和体系的嵌入式剧本引擎。Wez 是 PHP 的中心开辟人员,常常向 SQLite、COM/.Net、ActivePHP、mailparse 和 Streams API 等投稿,他是 PECL 即 PHP 扩大社区库的“头儿”。他的征询公司的网页为 http://www.thebrainroom.net。
资本
1.有关 PDO 法式包的更多信息
2.呈报新毛病? - 请供应能够有助于修复该毛病的任何信息。
3.用于 Oracle JDeveloper 的 PHP 扩大 - 该 PHP 扩大简化了 Oracle JDeveloper 10g 中 PHP 剧本的创立、编纂和运转
4.PHP 遨游者指南 - 懂得关于 PHP 的一切,从启动您的第一个使用法式到这类言语将具有如何的将来。
一些真正的强人总会搞出新玩意来丢给你,你不学就落后了,也印证了前人的经验,果然是学无止境啊! |
|