利用DB2 9原生XML和PHP来简化XML应用程序
简介
PHP 支持简单的 Web 应用程序开发和部署环境。这是它得到普遍应用的原因之一。DB2 9的原生 XML 功能进一步简化了开发过程。这种简化体现在以下方面:
登录后复制 登录后复制 登录后复制 登录后复制
|
为了说明我们的推理,将通过一个模拟在线商店的使用情景来进行说明,该商店向注册客户出售古董银器。
我们将在该情景中说明的一些要点包括:
登录后复制 登录后复制 登录后复制 登录后复制 |
登录后复制 登录后复制 登录后复制 登录后复制 |
为突出使用 DB2 原生 XML 支持对 PHP 应用程序代码和关系模式设计的影响,该情景将创建一个并行环境,该环境使用不包含任何 XML 功能的数据库(例如,MySQL)。我们将研究这两个环境在应用程序代码、数据库查询和关系模式方面的差异。还将说明选择特定代码、模式或查询以及备选方案(如果可能)的理由。
情景
该情景模拟向注册客户出售古董银器的在线商店。因为该情景的一个目的是说明不同的数据库环境以及它们对应用程序代码的影响,所以我们将对两个应用程序进行同时说明,一个应用程序使用 DB2 原生 XML,另一个应用程序使用类似 MySQL 的开放源码 RDMS,具有有限的 XML 功能或没有任何 XML 功能。
因此,访问 Web 站点的客户将看到一个包含两个垂直面板的页面。每个面板都将显示同一应用程序的一个版本,提供相同的用户体验,但在后端使用不同的数据库:
登录后复制 登录后复制 登录后复制 登录后复制 |
为显示应用程序代码的差异,每个面板进一步分为两个水平框架,上面的框架显示在线商店,下面部分显示代码段。当用户进行任何操作(如单击某一种类或产品图像)时,上面部分都会生成一个新页面。下面部分显示创建此页面所需的代码。
图 1. 示例应用程序面板
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=355 alt=示例应用程序面板 src="/files/uploadimg/20060809/1134560.jpg" width=572>
这将说明,虽然在任何一个应用程序中用户的体验没有变化,但代码复杂性发生了很大变化。这种对比将突出用 PHP 编写的普通 SMB 应用程序使用 DB2 原生 XML 功能的好处。
注意:我们对此情景的假设是业务数据已经是 XML 格式的,尽管数据库可能没有任何 XML 功能。这将产生可用于数据库的使用 XML 功能的 PHP 应用程序代码(如简单 DOM)。具有有限 XML 功能或无 XML 功能的数据库将 XML 数据存储为 CLOB/BLOB 数据类型,或分割到关系字段中。
在 Web 站点中浏览时的功能和用户体验
Web 站点将为用户提供索引,列出商店中所有可用银器的种类和品牌。用户单击某一种类或品牌时,将显示该种类或品牌的货品列表。选择列表中的任何货品都会在页面中显示该货品的详细信息。用户可以将这些货品添加到购物车中。一旦用户提交了订单,将会创建采购订单并根据此采购订单向用户提供发票。用户可以随时检查购物车中的货品。用户还能够得到他们过去已订购的所有货品的报告。
应用程序体系结构
图 2 显示了示例应用程序的基本体系结构。
图 2. 应用程序体系结构
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=431 alt=应用程序体系结构 src="/files/uploadimg/20060809/1134561.gif" width=473>
关系和 XML 模式
XML 文档和模式
原生 XML 存储不需要 XML 列与特定 XML 模式关联。需要对插入到数据库中的 XML 文档进行的任何验证都在插入语句中使用 SQL/XML 函数显式地进行。附录中包含 XML 文档示例。
关系模式
对于这两个数据库,用于存储这些 XML 文档的关系模式将有所不同。
对于 DB2 原生 XML,将有三个表,每个表包含两列。
图 3. DB2 原生 XML 模式
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=72 alt="原生 XML 情景的关系模式" src="/files/uploadimg/20060809/1134562.gif" width=460>
对于无 XML 支持的 RDBMS,将有四个表,每个表包含多个列:
图 4. 无 XML 支持的情景的关系模式
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=261 alt="无 XML 支持的情景的关系模式" src="/files/uploadimg/20060809/1134563.jpg" width=563>
可以看出,与无 XML 支持的 RDBMS 相比,DB2 原生 XML 的关系模式非常简单。
我们已经通过将采购订单文档存储为 BLOB,在基本关系数据库中尽量保持采购订单表模式简单。当查看生成订单历史记录时,这种操作的作用将非常明显。
DB2 PHP 驱动程序
在开始讲述 PHP 应用程序代码之前,我们先了解一下 PHP 的 DB2 驱动程序。ibm_db2 驱动程序支持两种连接数据库的方法:编目 和非编目。编目连接可以是本地数据库(如果有 DB2 服务器在本地运行),也可以是远程 DB2 服务器节点。第二种方法通常用于远程非编目连接,需要构建连接字符串(类似于 JDBC URL)以建立非编目连接。以下代码连接编目数据库。(客户机应用程序不需要知道或关注编目连接时本地的还是远程的。)
$conn = db2_connect($dbname, $dbuser, $dbpass); if(!$conn) { echo db2_conn_errormsg(); die("Unable to connect to database!"); } |
还可以使用 db2_pconnect 创建与数据库的持久连接。调用 db2_close 时,持久连接实际将不被关闭,因为连接句柄将在请求中保留。有关 PHP 的 IBM DB2 驱动程序的详细信息,请访问 http://www.php.net/manual/en/ref.ibm-db2.php。在下面的代码段中,假设 $conn 是有效连接句柄。
填充数据库
在 Web 站点可以开通之前,需要使用客户信息和产品目录填充数据库。对于我们的情景,将不详细说明如何获取此数据。假设其以 XML 文档的形式包含在本地文件系统的文件中。下面显示了连接数据库和执行 SQL 插入语句所需的 PHP 代码段示例。
DB2 Viper
因为每个产品文档都包含产品 ID 属性,我们需要使用 PHP 的 SimpleXml API 提取该 ID。
注意: 使用此 API 比操作 DOM 对象容易得多,该对象在 PHP 版本 5 之前是惟一选择。
- 创建数据库连接:
$conn =db2_connect($dbname, $dbuser, $dbpass);
- 从文件打开文档,成为一个变量:
$fileContents = file_get_contents("products/p1.xml");
- 从此变量创建简单的 XML 对象:
$dom = simplexml_load_string($fileContents);
- 从文档中提取产品 ID:
$prodID = (string) $dom["pid"];
- 创建准备好的语句,将 XML 文档插入数据库中:
$stmt =db2_prepare($conn, "INSERT INTO xmlproduct VALUES (?, ?)");
- 将从文档中提取的产品 ID 作为参数与文档一起传递到查询:
db2_execute($stmt, array($prodID, $fileContents);
注意: 这些代码段中的查询都使用斜体表示,以区别于 PHP 应用程序代码。
非 XML RDBMS
因为此数据库不具有任何 XML 功能,产品文档需要分解到两个关系表中。关系模式和 XML 模式之间的映射信息将直接嵌入 PHP 应用程序代码中。
- 首先加载文档到 DOM 中:
$fileContents = file_get_contents("$products/p1.xml");
$dom = simplexml_load_string($fileContents);
- 现在将产品的单个元素分割到本地变量中:
$prodID = (string) $dom["pid"];
$prodName = (string) $dom->description->name;
$prodDetails = (string) $dom->description->details;
$prodPrice = (float) $dom->description->price;
- 每个产品的图像 URL 需要存储在单独的图像表中:
$images = array();
foreach($dom->description->images->image as $image) {
switch((string) $image[type']) {
case thumbnail':$prodImgThumb = (string) $image;
$prodImgAlias = (string) $image[alias'];
if(!$prodImgAlias) $prodImgAlias = NULL;
$stmt = db2_prepare($conn, "INSERT INTO sqlimages (Pid, Type, Alias, Location) VALUES (?, ?, ?, ?)");
db2_execute($stmt, array($prodID, thumbnail', $prodImgAlias, $prodImgThumb));
case full':
$prodImgFull = (string) $image;
$prodImgAlias = (string) $image[alias'];
if(!$prodImgAlias) $prodImgAlias = NULL;
$stmt = db2_prepare($conn, "INSERT INTO sqlimages (Pid, Type, Alias, Location) VALUES (?, ?, ?, ?)");
db2_execute($stmt, array($prodID, full', $prodImgAlias, $prodImgFull));
}
}
- 当前实现 ibm_db2 驱动程序不能适当地将 NULL 变量作为参数来处理,以便执行函数;因此我们使用一个非强制性解决方案:
if(!$prodBrand) $prodBrand = " ";
if(!$prodCategory) $prodCategory = " ";
if(!$prodImgFull) $prodImgFull = " ";
- 现在保存产品表中的产品信息:
$stmt = db2_prepare($conn, "INSERT INTO sqlproduct (Pid, Name, Details, Brand,
Category, Price, Weight, Size, Description) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)");
db2_execute($stmt, array($prodID, $prodName,
$prodDetails, $prodBrand, $prodCategory,
$prodPrice, $prodWeight, $prodSize, $fileContents));
主页包含在线商店中所有可用产品的种类和品牌的索引。索引的右边区域显示所有货品的列表。
图 5. 主页
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=451 alt=主页 src="/files/uploadimg/20060809/1134564.jpg" width=438>
创建种类和品牌的索引列表
索引通过查询数据库中所有产品的惟一种类和品牌的列表而创建。启动应用程序时将创建此列表。
DB2 Viper
- 首先创建 DB2 视图,以使用 XQuery 列出种类,XQuery 在所有产品中循环并返回所有惟一种类:
CREATE VIEW Categories(Category) AS SELECT DISTINCT(XMLCAST(
XMLQUERY(for $i in $t/product/description/category return $i'
PASSING BY REF T.DESCRIPTION AS "t" RETURNING SEQUENCE)
AS VARCHAR(128))) FROM
xmlproduct AS t
- 现在从应用程序调用该视图:
$stmt = db2_exec($conn, "SELECT * FROM Categories");
while(list($cat) = db2_fetch_array($stmt)) {
echo "
";}
这两种情况中的应用程序代码相似。创建 XML 数据视图使我们可以轻松地查询视图,从而有助于从应用程序代码理解产品 XML 的结构。需要更改视图中的 XQuery 以查找品牌元素,同样 SQL 调用也需要查看 Brand 列。
模式演化对索引列表的影响
根据客户反馈,我们需要允许用户浏览站点,以查找镀银的货品或由纯银制造的货品。我们看一下向索引中添加子种类对以下各项的影响:XML 模式、关系模式、查询和 PHP 应用程序代码。
对 XML 模式和文档实例的影响
向产品 XML 模式中的种类元素添加新属性(catx)。产品的所有新 XML 文档现在都用纯银或镀银适当地填充了此属性:Miscellaneous
对关系模式的影响- DB2 Viper
这将不需要对关系模式进行任何更改,因为 XML 文档存储在单个列中。 - 非 XML RDBMS
在基本关系数据库中,将需要更改产品表的模式,添加名为 catx 的另一列。这可能涉及删除并重新插入所有产品文档。
- DB2 Viper 创建索引所需的 XQuery 将发生变化以在条件中包含这个新属性。同样,用于根据索引中的选择列出货品 XQuery 也将发生变化来包括新条件。
- 非 XML RDBMS
插入语句将发生变化以包括新列。
对应用程序代码的影响- DB2 Viper
应用程序代码将没有任何更改。 - 非 XML RDBMS
- 将需要额外的 DOM 代码,以分割出子种类信息。
- INSERT 语句将需要额外的参数。
- 所有数据都有可能需要重新插入,这导致终端用户有一段时间无法操作。
用户单击特定种类或品牌时,将生成该种类或品牌中所有货品的列表。列表中的每个货品都有简短描述和到缩略图像的 URL。此列表显示在主页中并在其中进行格式设置。
图 6. 某一种类中的货品列表
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=356 alt=某一种类中的货品列表 src="/files/uploadimg/20060809/1134565.jpg" width=572>
DB2 Viper
在 DB2 中,XQuery 不仅创建列表,而且还将其转换为 HTML 输出,从而浏览器可以直接使用。使用 XQuery 的此功能,不仅可以推出业务逻辑,而且可以发布到数据库服务器,从而有效地使中间层应用程序非常简单。这正是使用 PHP 而不使用 Java™ 或 VS .NET® 的原因。
$xquery =for $i in $t/product
let $thumb := $i/description/images/image[@type="thumbnail"]
where $i/description/category = " . htmlentities($category) . "
return
- DB2 Viper

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

本教程演示了如何使用PHP有效地处理XML文档。 XML(可扩展的标记语言)是一种用于人类可读性和机器解析的多功能文本标记语言。它通常用于数据存储

字符串是由字符组成的序列,包括字母、数字和符号。本教程将学习如何使用不同的方法在PHP中计算给定字符串中元音的数量。英语中的元音是a、e、i、o、u,它们可以是大写或小写。 什么是元音? 元音是代表特定语音的字母字符。英语中共有五个元音,包括大写和小写: a, e, i, o, u 示例 1 输入:字符串 = "Tutorialspoint" 输出:6 解释 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。总共有 6 个元

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

PHP的魔法方法有哪些?PHP的魔法方法包括:1.\_\_construct,用于初始化对象;2.\_\_destruct,用于清理资源;3.\_\_call,处理不存在的方法调用;4.\_\_get,实现动态属性访问;5.\_\_set,实现动态属性设置。这些方法在特定情况下自动调用,提升代码的灵活性和效率。

在PHP8 中,match表达式是一种新的控制结构,用于根据表达式的值返回不同的结果。1)它类似于switch语句,但返回值而非执行语句块。2)match表达式使用严格比较(===),提升了安全性。3)它避免了switch语句中可能的break遗漏问题,增强了代码的简洁性和可读性。
