在PHP与DB2 9中使用Ajax:Xajax
PHP 是常用于开发 Web 应用程序的一种脚本编制语言。 Asynchronous JavaScript and XML (Ajax) 则是组合 JavaScript、 Document Object Model (DOM) 和 XMLHttpRequest 技术,以提供客户机与服务器之间的动态交互的一种 Web 技术。有很多用于与 PHP 一起使用 Ajax 的 PHP 类库,Xajax 就是其中一个,它是开放源代码的、面向对象的 PHP 类库。在本文中,学习如何实现 PHP、Ajax 和 Xajax,以开发一个访问 IBM® DB2® 9 for Linux®, Unix®, and Windows® 的动态 Web 应用程序解决方案。
简介
目前,超过 40% 的 Web 应用程序使用 PHP 作为脚本编制语言。Asynchronous JavaScript and XML (Ajax) 是组合 JavaScript、 Document Object Model (DOM) 和 XMLHttpRequest 技术,以提供客户机与服务器之间的动态交互的一种 Web 技术。有很多用于与 PHP 一起使用 Ajax 的 PHP 类库,Xajax 就是其中一个,它是开放源代码的、面向对象的 PHP 类库,通过它可以在 PHP 中使用 Ajax。
举个例子,假设有一名用户正在填写一份表单,以便在一个 Web 站点上注册。通常,只有在提交表单时才会检查表单数据的有效性。但是如果使用 Ajax,将使用服务器应用程序中的业务逻辑动态验证添加到表单的数据。 因此,不必将整个表单提交到服务器以检查表单中的数据是否有效。异步(Asynchronous)意味着 XMLHttpRequest 对象的 send() 方法可以立即返回,不必等待 HTTP 请求完成,而发出请求的 HTML/JavaScript 页面则可以继续进行其他的处理。因此,开发人员可以发现,当 XMLHttpRequest 对象异步地处理 HTTP 响应时,可以继续处理发出 XMLHttpRequest 请求的 HTML/JavaScript 页面。
Xajax 概述
Xajax 用于以 PHP 脚本编写的客户机应用程序和服务器端应用程序之间进行异步的通信。对于可能从客户机应用程序访问的服务器端的 PHP 函数,Xajax 为之生成 JavaScript 包装器函数。当一个客户机应用程序调用包装器函数时,会生成一个 XMLHttpRequest 对象,并将一个 XMLHttpRequest HTTP 请求发送到服务器。
在服务器上,xajax 对象收到 XMLHttpRequest,并调用与 JavaScript 包装器函数对应的 PHP 函数。通过 Xajax 注册的 PHP 函数的默认请求类型是 POST。PHP 函数返回一个 XML 响应,后者由 xajax 对象返回到客户机应用程序。根据 XML 响应中的指示,Xajax 的 JavaScript 消息泵更新客户机输入页面的内容。Xajax 的一个特性可以确保只有已经被修改的数据才会被更新。
要开始创建自己的 Web 应用程序,我们首先看看安装产品和创建数据库的步骤。然后,您就可以深入研究应用程序的创建。
安装 DB2 for Linux, UNIX, and Windows
用于 DB2 数据库的 PHP 扩展可以与 DB2 for Linux, UNIX, and Windows V8.2 或更高版本一起使用。下面的安装说明使用 DB2 EntERPrise 9 for Windows:
下载 DB2 9 数据服务器(见 参考资料)。(本例使用的是 DB2 Enterprise 9,但实际上也可以使用其他版本的 DB2。)
将 db2_v9_ese_win_32.zip 解压到一个目录。
要安装 DB2,双击 C:DB2ESEimagesetup.exe 应用程序。
在 IBM DB2 Setup Launchpad 中,单击 Install a Product。
在 DB2 Enterprise Server 的标签中单击 Install New。这时会出现 DB2 Setup 向导。单击 Next。
接受许可协议,然后单击 Next。
选择一种安装类型(典型安装),然后单击 Next。
选择 installation and response file creation(默认),然后单击 Next。
选择一个安装文件夹(默认为 C:Program FilesIBMSQLLIB),然后单击 Next。
指定用户名(db2)和密码(db2admin),然后单击 Next。
DB2 实例 DB2 作为默认 DB2 实例被列出来。通过单击 Configure 按钮,可以为默认 DB2 实例配置服务名称和协议。默认服务名称为 db2c_DB2,默认端口为 5000。单击 Next。
在 Prepare the DB2 tools 类别框架中选择默认设置,然后单击 Next。
如有必要,设置通知,然后单击 Next。
在 Enable operating system security for DB2 objects 中选择默认设置,然后单击 Next。
单击 Finish 按钮安装数据库服务器。
现在创建一个示例数据库。作为先决条件,将 DB2INSTANCE 环境变量设置为 DB2:选择 System Properties > Advanced > Environment Variables > System Variables。也可以在 DB2 命令窗口中使用以下命令来设置 DB2INSTANCE 环境变量:
set DB2INSTANCE=DB2
要创建一个示例数据库,在 DB2 First Steps 框架中选择 Database Creation。单击 Create SAMPLE Database 按钮。 也可以使用以下命令创建示例数据库:
db2sampl
使用以下 DB2 命令将 DB2 数据库 SAMPLE 注册为 ODBC 数据源:
db2 catalog system odbc data source sample
安装 PHP 和 Xajax
Xajax 是一个 PHP 类库,因此首先下载和安装 PHP 5。PHP 5 可以安装在很多不同的 Web 服务器上。本文讨论在 Windows 上使用 Apache Web 服务器配置 PHP 5。
下面是安装和配置 PHP 的步骤:
下载 PHP 5.2.0 (见 参考资料)。
将 PHP zip 文件解压到一个安装目录中(例如 C:/PHP)。
下载和安装 Apache HTTP Server 2.0。
在 PATH 环境系统变量中添加安装 PHP 5 的目录(C:/PHP)。
将 C:/PHP 目录中的 php.init 文件修改为 php.ini。
本文中的示例应用程序从 DB2 数据库中存取数据。您将使用 PHP PDO 扩展连接到 DB2 数据库。
在 php.ini 配置文件中,需要通过指定 extension_dir = "./ext" 设置扩展目录。要激活 PDO 扩展,需要去掉 php.ini 文件中下面这一行前面的 ‘;’:
extension=php_pdo.dll
此外还需要激活 PDO ODBC 驱动程序。在 php.ini 文件中,去掉下面这一行前面的 ‘;’:
extension=php_pdo_odbc.dll
将 PHP 5 安装在 Apache HTTP 服务器中。在 /conf/httpd.conf 文件中,添加:
# For PHP 5
LoadModule php5_module "C:/PHP/php5apache2.dll"
AddType application/x-httpd-php .php
# configure the path to php.ini
PHPIniDir "C:/PHP/"
默认情况下, 目录是目录 C:/Program Files/Apache Group/Apache2。我们已经在 C:/Apache2/Apache2 目录中安装了 Apache2 服务器。如果 PHP 5 被安装到 C:/PHP 以外的目录中,那么用那个目录替换 C:/PHP。在修改 httpd.conf 目录之后,重新启动 Apache Web 服务器。将要在 Apache Web 服务器中运行的 PHP 文件复制到 C:/Apache2/Apache2/htdocs 目录中。
下载 Xajax 0.2.4。在 C:/Apache2/Apache2/htdocs 目录中创建一个 xajax 目录。将 xajax_0.2.4.zip 文件解压到 xajax 目录中。
创建 DB2 数据库表
Xajax 应用程序从一个 DB2 数据库表中检索数据。可以用一个 PHP 脚本创建这个数据库表。创建一个 PHP 脚本 createTable.php。定义用于用户名和密码的变量:
$user = 'db2';
$password = 'db2admin';
使用 PDO 构造函数获得与 DB2 SAMPLE 数据库的连接:
$connection = new PDO('odbc:SAMPLE', $user, $password);
默认情况下,PDO 构造函数创建一个非持久的连接。如果连接成功,则 PDO 构造函数返回一个 DB2 数据库连接资源。当连接成功时,输出消息为 “Connection succeeded”。当数据库连接失败时,会输出连接错误消息。定义用于创建一个表的 SQL 语句:
$createtable = "CREATE TABLE DB2.Catalog(CatalogId VARCHAR(25),
Journal VARCHAR(25), Section Varchar(25), Edition
VARCHAR(25), Title Varchar(45), Author Varchar(25))";
使用 exec() 函数运行该 SQL 语句:
$connection->exec($createtable);
定义用于向表中添加一行的 SQL 语句:
$addrow = "INSERT INTO DB2.Catalog VALUES('catalog1', 'IBM developerWorks',
'XML', 'July 2006', 'The Java XPath API', 'Elliotte Harold')";
使用 exec() 函数运行该 SQL 语句:
$result=$connection->exec($addrow);
这样就在数据库表中添加了一行。输出消息,以表明被添加的行数:
print("Added $result rows.n");
类似地,将另外一行添加到数据库表 Catalog 中:
$addrow = "INSERT INTO DB2.Catalog VALUES('catalog2', 'IBM developerWorks',
'XML', 'October 2005', 'JAXP validation', 'Brett McLaughlin')";
$result=$connection->exec($addrow);
清单 1 中显示了 PHP scriptcreateTable.php。将 createTable.php 复制到 C:/Apache2/Apache2/htdocs 目录。启动 Apache Web 服务器(如果没有启动的话)。在一个浏览器中通过 URL 运行这个 PHP 脚本。这样将生成一个数据库表 DB2.Catalog,并向这个表中添加数据。
清单 1. createTable.php
<?php
try {
$user = 'db2';
$password = 'db2admin';
$connection = new PDO('odbc:SAMPLE', $user, $password);
echo "Connection succeededn";
$createtable = "CREATE TABLE DB2.Catalog(CatalogId VARCHAR(25),
Journal VARCHAR(25), Section Varchar(25), Edition
VARCHAR(25), Title Varchar(45), Author Varchar(25))";
$connection->exec($createtable);
$addrow = "INSERT INTO DB2.Catalog VALUES('catalog1', 'IBM developerWorks',
'XML', 'July 2006', 'The Java XPath API',
'Elliotte Harold')";
$result=$connection->exec($addrow);
print("Added $result rows.n");
$addrow = "INSERT INTO DB2.Catalog VALUES('catalog2', 'IBM developerWorks',
'XML', 'October 2005', 'JAXP validation',
'Brett McLaughlin')";
$result=$connection->exec($addrow);
} catch (PDOException $e) {
$e->getMessage();
}
?>
发送一个请求
现在我们来开发包含一个输入表单的示例应用程序。输入表单收集用于将一个类别条目添加到数据库表 Catalog 中的数据。当用户开始在输入字段 Catalog Id 中输入数据时,一个 XMLHttpRequest HTTP 请求被发送到服务器,以验证添加的 Catalog Id 的值。如果数据库中还没有定义 Catalog Id,则显示消息 “Catalog Id is Valid”。如果数据库中已经定义了这个 Catalog Id,则显示消息 “Catalog Id is not Valid”,同时禁用 Create Catalog 按钮,Catalog Id 的字段值被添加到表单中。
xajax PHP 对象在客户机应用程序与服务器之间起中介的作用。首先,将 xajax 类库包括进来:
require('./xajax/xajax_0.2.4/xajax.inc.php');
创建一个 xajax 对象:
$xajax = new xajax();
服务器端的处理由 PHP 函数来执行。创建 PHP 函数 validateCatalogId($formValues) 和 updateCatalog($formValues)。这两个函数都带有一个 $formValues 参数:
function validateCatalogId($formValues){}
function updateCatalog($formValues){}
使用 reGISterFunction() 方法将这些 PHP 函数注册到 xajax 对象。xajax 对象为可能从 PHP 脚本或输入表单事件处理程序中调用的 PHP 函数创建包装器函数。
$xajax->registerFunction("validateCatalogId");
$xajax->registerFunction("updateCatalog");
Xajax 为注册的 PHP 函数生成异步包装器函数。包装器函数名称的格式为 xajax_phpfunction。 变量 phpfunction 是要为之定义包装器函数的一个服务器端 PHP 函数。Xajax 通过 getFormValues(string formId) 方法提供异步表单处理。 通过使用 getFormValues() 方法,可以将表单字段值数组作为参数提交给一个 xajax 异步包装器函数。 还可以使用 getFormValues(string formID ,boolean submitDisabledElements, string prefix]) 函数提交表单的一部分,而不是提交整个表单。prefix 参数指定只有以该前缀开头的表单元素应该被提交。布尔参数 submitDisabledElements 指定是否提交被禁用的元素。PHP 函数 validateCatalogId 和 updateCatalog 为表单字段值数组定义了一个参数。在发出 XMLHttpRequest 之前,用 processRequests() 函数指定用于处理请求的 xajax 对象:
$xajax->processRequests();
此外还在输入表单的 标记中指定,在服务器返回 XML 响应之后,xajax 应该生成任何需要的 JavaScript:
printJavascript('./xajax/xajax_0.2.4');
?>
客户机应用程序发出一个 XMLHttpRequest。在示例应用程序中,XMLHttpRequest 是由输入字段 catalogId 的 onkeyup 事件处理程序发出的:
tr><td>Catalog Id:</td><td><input type="text"
size="20"
id="catalogId"
name="catalogId"
autocomplete="off"
onkeyup="xajax_validateCatalogId(xajax.getFormValues
('validationForm'));"></td>
<td><div id="validationMessage"></div></td>
</tr>
输入字段调用包装器函数 xajax_validateCatalogId,调用时以表单字段值数组作为参数。包装器函数将一个 XMLHttpRequest 发送到服务器。xajax 对象接收 XMLHttpRequest,并调用相应的 PHP 函数 validateCatalogId($formValues)。
处理请求
Xajax 提供 xajaxResponse 类,用于将响应发送回客户机应用程序。在 validateCatalogId 函数中,创建一个 xajaxResponse 对象:
$objResponse = new xajaxResponse();
validateCatalogId 函数验证添加到输入表单中的 Catalog Id 值。从 $formValues 数组中,检索 catalogId 字段的值:
$catalogId=trim($formValues['catalogId']);
接下来,使用 PHP PDO 扩展连接到 DB2 数据库,并判断 Catalog 表中是否为输入表单中输入的 catalog id 值定义了一行。
定义用于用户名和密码的变量:
$user = 'db2';
$password = 'db2admin';
使用 PDO 构造函数获得与 DB2 数据库的一个连接:
$connection = new PDO('odbc:SAMPLE', $user, $password);
如果连接成功,PDO 构造函数返回一个 DB2 数据库连接资源。准备一个 SQL 预置语句,该 SQL 语句从 Catalog 表中选择与表单中输入的 catalog id 值对应的一行。使用 prepare ( string statement [, array driver_options] ) 函数编译预置语句:
$stmt = $connection->prepare("SELECT * from DB2.CATALOG WHERE CATALOGID=?");
使用 PDO::ATTR_CURSOR 属性将游标设置为可滚动游标:
$stmt ->setAttribute(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL);
使用 bindParam() 方法绑定 CatalogId 参数:
$stmt->bindParam(1, $catalogId);
用 execute ( [array input_parameters] ) 函数执行预置语句中的 SQL 查询:
$stmt->execute();
使用 fetch ( [int fetch_style [, int cursor_orientation [, int cursor_offset]]] ) 函数获取结果集中的行:
$row = $stmt->fetch();
如果被请求的行存在,则 fetch() 函数返回 TRUE,如果被请求的行不存在,则返回 FALSE。如果 fetch() 返回 FALSE,则结果集为空,表明数据库表中还没有为 catalog id 值定义一个 Catalog 表行。因此,表单中添加的 Catalog Id 字段值是有效的。接下来,生成一个发送到客户机应用程序的响应。一个响应包含一个或多个命令消息。表 1 讨论了一些常用的命令消息:
表 1. xajaxResponse 命令消息
命令消息描述
Assign使用方法 addAssign(string elementId, string attribute, string data) 设置输入页面中一个元素的指定属性
Append使用方法 addAppend(string elementId, string attribute, string data) 将数据附加到输入页面中一个元素的指定属性
Prepend使用方法 addPrepend(string elementId, string attribute, string data) 将数据设置为输入页面中一个元素的指定属性的预定值
Replace使用方法 addReplace(string elementId, string attribute, string replace, string data) 替换输入页面中一个元素的指定属性中的数据
Script使用方法 addScript(string javascript) 运行指定的 JavaScript 代码
Alert使用方法 addAlert(string message) 显示包含指定消息的警告对话框
如果 fetch() 方法返回 FALSE,则 validationMessage div 中显示消息:"Catalog Id is Valid"。addAssign 方法设置 validationMessage div 的 innerHTML。
$objResponse->addAssign("validationMessage","innerHTML","Catalog Id is Valid");
如果 fetch() 函数返回 TRUE,则 Catalog 表中已经定义了这个 catalog id 值。 因此,输入表单中添加的 Catalog Id 值是无效的。如果 fetch() 方法返回一行,则将 validationMessage div 的 innerHTML 设置为 “Catalog Id is not Valid”:
$objResponse->addAssign("validationMessage","innerHTML","Catalog Id is not Valid");
接下来,从结果集行中取值,设置输入表单字段中的值。fetch() 函数将结果集指针指向下一行。
用 $row[mixed column] 函数从结果集行中获取字段值。column 参数可以指定为列索引(从 0 开始计数)或列名。例如,journal 列值可以用以下清单中的 PHP 代码获得:
$journal=$row['JOURNAL'];
用 addAssign 方法设置输入表单字段元素的 value 属性。例如,像下面这样设置 journal 元素的 value 属性:
$objResponse->addAssign("journal","value",$journal);
此外,禁用 submit 按钮:
$objResponse->addAssign("submitForm","disabled",true);
从 validateCatalogId 函数以 XML 字符串的形式返回 $objResponse 对象:
return $objResponse->getXML();
XML 响应被发送至 xajax 处理程序,后者将 XML 响应发送至 xajax 的 JavaScript 消息泵。消息泵解析 XML 指令,并设置输入页面中的元素。因此,在 $xmlResponse 对象中用 addAssign 方法指定的数据被设置到输入表单中。
updateCatalog($formValues) 函数用于根据输入表单更新数据库表 Catalog。如果 Catalog Id 字段值有效,则为 表单的其他字段添加值,以创建一个新的类别条目。单击 Create Catalog 按钮提交表单。onsubmit 事件处理程序调用包装器函数 xajax_updateCatalog,后者发送一个 XMLHttpRequest 到服务器:
onsubmit="xajax_updateCatalog(xajax.getFormValues('validationForm'));"
xajax 对象接收 XMLHttpRequest,并调用相应的 PHP 函数 updateCatalog($formValues)。在 updateCatalog 函数中,获取表单字段值,并创建一条 SQL 语句,以便将一行添加到数据库表 Catalog 中。获得与数据库的连接,并运行 SQL 语句。清单 2 中列出了 input.php 脚本: