如何使用数据库
任何快速开发中等复杂度的 Web 应用程序的人都发现,页面之间的持续变量只能短暂地保存信息。这就是要引入数据库的原因;Oracle 已做好了充分的准备来满足这种需求。
那么我们如何把 PHP 与 Oracle 结合在一起?与 PHP 的传统保持一致,这个过程非常简单:提供用户名和口令以及数据库连接详细资料,您就可以快速地与 Oracle 连接来存储和检索数据。
例如,假定我们创建了一个名为 "example" 的表,它有两列,分别是名和姓。(确保为 Apache user 设置了 ORACLE_HOME 和 ORACLE_SID。)与 Oracle 数据库连接是一件简单的事情:
<HTML>
<TITLE>First Variables Example</TITLE>
<BODY>
<?php
$tns = ''sean'';
$user = "scott@$tns";
$pass = ''tiger'';
$q1 = ''SELECT * FROM example'';
$conn = ora_logon($user, $pass);
$mycursor ora_open ($conn);
ora_parse ($mycursor, $q1, 0);
ora_exec ($mycursor);
while (ora_fetch($mycursor)) {
echo "RESULT:ora_getcolumn ($mycursor, 0), ora_getcolumn ($mycursor, 1) <br>";
}
ora_close($mycursor);
?>
</BODY>
</HTML>
如果您计划使用 PHP 扩展的 PEAR 库(稍后再详述),那么您应该了解一下 PEAR DB。PEAR DB 提供了一个数据库抽象层,这个抽象层允许您编写应用程序,并且只修改 conntion 描述符来与一个不同类型的数据库连接(比如说,与 MySQL 上的原型连接并使用 Oracle 进行生产)。数据库抽象意味着您的应用程序不是被束缚在一个数据库上,而是可以在无数的数据库上工作。然而,它也意味着您不得不接受特性的最小公分母。因此您的体验可能会有所不同。
特性概述
条件、循环和运算符
像所有的迭代编程语言一样,PHP 通过 if/then 语句支持条件。这是一个语法示例:
if ($a > 100) {
do this...
} elseif ($a > 50) {
do that...
} else {
do some other thing...
}
它还通过 switch 或称为 case 语句来支持类似功能。然后,当然有循环,这由条件在最初指定的 WHILE 和在最后指定的 DO...WHILE,以及在一开始指定迭代次数的 FOR 来支持。例如:
while ($notdone == 0) {
some code here...
if (some condition) {
$notdone = 1;
}
}
至于运算符,您将发现您所期望的全部,包括用于基本数学运算的 +、-、*、/,用于求模的 %,和用于比较运算的 >、>=、<=、!= 和 <>。 此外还包括了由关键字 AND (&&)、OR (||) 、XOR、和用于求非的 ! 提供的逻辑运算符。 注意 = 是赋值,而 == 是相等比较。 您还可以使用 ''.'' 运算符来连接字符串。 (这些功能大部分和 Perl 和其它脚本语言的功能类似。关于详细情况,请参见您的 PHP 手册。)
支持的数据类型
PHP 通过 DEFINE 语句、整数、浮点值、字符串、不同类型的数组和面向对象编程中使用的抽象对象类型来支持常量。当您创建了一个变量时,PHP 根据它的初始值来设定类型。例如,如果您给定了一个值 2,PHP 将创建一个整数 (2.0)、一个浮点数 ("2.0") 和一个字符串。
正则表达式
PHP 的最出色的特性之一是它为正则表达式提供的支持。正则表达式通过 grep、egrep、awk 和使用诸如 sh、csh 和 Perl 之类的语言编写的脚本在 Unix 中使用。从根本上说,正则表达式指定一种模式,引擎将对照该模式进行比较,以找到字符串内容或替换它们(或二者都进行)。
例如,假定您有一个 web 表单,其中用户指定了一个电子邮件地址,而您想要确认它有效。(参见安全性部分来了解为什么检验表单中的输入值是如此重要。)这一小段代码将为您实现这个目的:
if (ereg ("^.+@.+\\..+$", $inEmail)) {
do something with your email address...
?} else {
address is invalid, discard and/or return error
}
Oracle API
因为如此多的基于 Web 的应用程序需要与后端上的 Oracle 连接,所以 PHP 从一开始就提供了这种支持。还有一个 Oracle8 专用的 API,它允许您使用 Oracle 的一些更专门化的特性。
如果您正在构建的应用程序确实需要这些特性,那么就使用它们,但记住使用这个库将使您的应用程序被限制在这一平台上。您可以始终拖延,在您的应用程序成熟时使用这些特性,并要求更复杂的功能。
XML API
XML 实质上是标记语言的一种抽象。如果您把 HTML 看作是一种标记语言的一个特殊的实例,那么 XML 就是元 HTML (如果您愿意这么看的话)。它允许创建任意的定义来指定和分解您的特殊内容。例如,如果您有一个电子商务站点,它在一个目录中给出产品列表,则您可以使用类似下面的标记:
<products>
<item>
<prod_name>Blue Widget</prod_name>
<price>$29.95</price>
<description>
This widget is very blue in color, and good for many things.
</description>
</item>
<item>
<prod_name>Green Widget</prod_name>
<price>$24.95</price>
<description>
This widget is very green in color, and good for many things.
</description>
</item>
</products>
PHP 为 XML 提供了完善的支持,因此您可以在您的应用程序中使用这项出色的技术 — 如为您的 web 站点构建一个 datafeed,或者创建一种格式,利用这种格式可以容易地把外部信息整合到您的站点中。
图像处理
您的应用程序是否需要包含显示和操作产品、徽标、地图和人的图像,或根据存储在数据库中的信息绘制图形?PHP 的图像操作 API 为所有这些目的提供了支持。其中一些特性包括管理 Postscript 文件,处理字体和颜色,绘图和标点,以及图像大小缩放和修改。
PHP 和安全性
当解决 PHP + Oracle 的环境中的安全性时,存在许多需要考虑的问题。让我们依次来了解它们。
首先,您的网络需要是安全的 — 可能通过一个防火墙,它只允许通过端口 80 或端口 443 (分别用于 HTTP 和 HTTPS)进行通信。确保您的网络安全可能还涉及到为远程用户建立一个 VPN。
然而,此外您还应当通过使用好的口令、禁止不用的端口和服务、并使用为脆弱性提供的最新补丁,确保防火墙后的每一台计算机是安全的。一个开始的好地方是 http://securityfocus.com — 所有类型平台的安全性信息的一个交流中心。
当然,如果在后端上没有 Oracle 数据库,则所有基于 web 的应用程序都将失去价值。除了大家所关心的所有标准 OS 层的安全性问题之外,您的数据库还应使用好的口令,并设置文件权限,以使除 ''oracle'' 之外的用户不能修改或干预数据库文件自身。(请定期查看 http://metalink.oracle.com,以获取脆弱性信息和相关的补丁,并尽快应用它们。)但不要过于放松警惕:Oracle 数据库的安全性仅与 Unix 级的权限保持一致。比如说,如果用户拥有读数据文件的权限,则他们可以利用一个十六进制的编辑器来查看数据文件。
除了这些要关心的问题之外,确保牢记那些与模式、角色和授权相关的问题。根据经验的做法是,不授予用户权限,然后只逐渐增加他们完成工作必需的那些权限。同样的做法也适用于系统权限、创建对象和确定用户可以看到哪些对象。
最后,牢记应用程序级的安全性。实际上,当构建一个基于 web 的应用程序时,尽量试着极端一点:不断创造性地去思考黑客可能会试图做什么恶意的事情。Pete Finnigan 有一个专门讨论 Oracle 安全性的出色的 web 站点,并且他的一篇论文“SQL Injection 和 Oracle”直接谈到了这些大家所关心的问题。
利用类和对象进行模块化编程
在面向对象的编程语言出现之前,库是重用组件的首选工具。现在已经出现了 C++、Java 和许多其它的面向对象的语言,它们为代码重用提供了一种更先进、更不易出错的机制。PHP 也提供了这种功能,这是一件好事 — 因为任何中等复杂的 web 站点都需要它。
例如,如果您在构建一个财务应用程序,您希望将您的所有财务公式和例程封装到可被重复调用的类或库中。如果您在构建一个电子商务站点,您希望将税收、信用卡处理的计算封装到独立的库中,并且可以在任何需要的时候包含这些库。
让我们分析一个非常简单的例子来说明 PHP 中的这个概念。这是我建立的一个名为 someMath 的类:
<?
class someMath {
var $defaultPower = 2;
function someMath ($inPower) {
$this->defaultPower = $inPower;
}
function defPower ($inNum) {
return $this->doPower ($inNum, $this->defaultPower);
}
function doPower ($inNum, $inPower) {
return pow ($inNum, $inPower);
}
function setPower ($inNum) {
$this->defaultPower = $inNum;
}
function getPower () {
return $this->defaultPower;
}
}
?>
您可以看到,PHP 已经提供了一个函数来计算幂,因此这个类除了用一种非常简单的方式来演示如何将功能封装在类(您可以在整个代码范围内使用这些类)中之外,没有更多的意义。
第一个函数是构造函数,传统上用来初始化您的类中的变量。构造函数始终具有和类本身相同的名称。接下来您看到两个类似的函数:一个函数使用类中设置的默认次方来计算幂,另一个函数要求您在每次调用它时告诉它您想要多少次方。注意 defPower 函数仅调用包含了类 $defaultPower 变量的 doPower 函数。最后,setPower 和 getPower 函数允许您与变量进行交互,否则这些变量将被隐藏在类外。
现在我们再用一段代码来使用我们的类:
<HTML>
<TITLE>my class test</TITLE>
<BODY>
<H1>Testing someMath class</H1><p>
<H2>
<?php
require ("somemath.php3");
$mytest = new someMath (2);
$ansA = $mytest->defPower (10);
$ansB = $mytest->doPower (10,3);
$ansC = $mytest->doPower (2,8);
$ansD = $mytest->doPower (2,32);
echo "10 to the power of 2 is:$ansA<br>";
echo "10 to the power of 3 is:$ansB<br>";
echo "2 to the power of 8 is:$ansC<br>";
echo "2 to the power of 32 is:$ansD<p>";
?>
</H2>
</BODY>
</HTML>
就是这么容易。您可以看到,我们以不同的方式使用了我们的类中的一些函数来计算不同的幂。当然可以扩展这些想法来为您的应用程序封装复杂的代码和功能。
随着 PHP 的发展,许多程序员开发了他们自己的代码模块并将它们用于整个项目,从而促进了这一发展势头。历史上这种发展无章可循,直到创建了 PHP 扩展和应用程序信息库 (PEAR)。
PEAR 提供了编码标准、一个基础类 (PFC) 集合、一个 web 站点和邮寄列表,从而使混乱的局面有序化。总而言之,它提供了一种结构 — 凭借该结构程序员可以推动整个 PHP 项目并促进接受新代码的标准。此外,如果您希望创建 PHP 的扩展,也为此提供了余地。
PHP 上路
PHP 的全部就是实用性;它是以速度和快速部署为理念而构建的。因此虽然它提供了大量高级和复杂的特性,但它也可以非常快速直接地解决您的问题。