2009-04-01
Working PHP and Oracle under Redhat EL 5
众所周知,PHP对MySQL的接口做得很好,LAMP名声在外,但是对于其他数据库的支持貌似就差了点。以前试着用过一次PHP的SQLServer接口(mssql),感受是做得相当粗糙。但是考虑到SQLServer是windows阵营的,应用也仅限于windows操作系统,也就情有可原了。但是对于Oracle这个重量级&跨平台通吃的家伙,PHP的支持又怎样呢?
手册中有两个关于Oracle的函数库。其中一个名为Oracle Functions,是比较旧的哪个版本,已经废弃。第二个为OCI8 函数库,是当前使用的版本。基本上实现了OCI的功能(包括事务与LOB操作等),看起来还不错(没用过,因此性能有待考证)。
顾名思义,OCI8函数库使用OCI实现,而使用OCI是必须要安装Oracle提供的客户端的。虽然Oracle的客户端是免费软件,但并不是自由软件,所以一般的发行版在打包的时候不会包含进来。因此,需要自己动手配置一下才能使用。
下面的步骤在Redhat EL 5上测试通过,在其他发行版上应该也是大同小异,写在这里以供参考。
1、安装配置Oracle客户端
a) 下载Oracle Instant Client
下载basic,sdk,sqlplus三个包
instantclient-basic-linux32-11.1.0.7.zip instantclient-sdk-linux32-11.1.0.7.zip instantclient-sqlplus-linux32-11.1.0.7.zip
b) 安装并配置
按照Oracle的传统,放在/opt下
# mkdir /opt/oracle # unzip instantclient-basic-linux32-11.1.0.7.zip # unzip instantclient-sdk-linux32-11.1.0.7.zip # unzip instantclient-sqlplus-linux32-11.1.0.7.zip
解压完后都在一同个目录instantclient_11_1中
# mv instantclient_11_1 /opt/oracle/instantclient
编写tnsnames.ora
# mkdir -p /opt/oracle/instantclient/network/admin # cd /opt/oracle/instantclient/network/admin # vi tnsnames.ora
填入如下内容
ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.101.251)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORCL) ) )
其中HOST为Oracle服务器的IP,SERVICE_NAME为Oracle实例名。
在/etc/profile的最后中添加如下内容
export ORACLE_HOME=/opt/oracle/instantclient export TNS_ADMIN=/opt/oracle/instantclient/network/admin export LD_LIBRARY_PATH=/opt/oracle/instantclient export ORACLE_SID=ORCL
使配置生效
# source /etc/profile
将sqlplus放入bash寻找路径
# cp sqlplus /usr/local/bin
测试一下:
# sqlplus sys/sys@ORCL as sysdba
如果显示
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 – Production
SQL>
表示Oracle Instant Client配置成功。
2、安装PHP相关组件
虽然手册中说OCI8 Functions是内建在PHP中的,不需要安装,但是运行oci_connect()时,提示
Fatal error: Call to undefined function oci_connect() ……
究其原因,是因为虽然“内建”,但在默认编译时时并没有包含。解决方法有两个:一是从源代码重新编译PHP,具体步骤可以看这里;二是使用PECL中的oci8扩展。
按方便程度来说,最好的选择自然是后者。过程如下:
PECL和PEAR使用同一套包管理系统,所以要先安装PEAR才能使用PECL。
至于PHP开发包么,是因为PECL取回的是源代码,需要开发包来编译扩展,所以也是必需的。
使用yum,可以很简单地搞定这些。
# yum install php-pear # yum install php-devel
编译安装前,还需要做一项准备工作。(共享库文件是带版本号的,默认编译时无法找到,需要建立没有版本号的共享库文件。用符号连接即可解决问题)
# ln -s libclntsh.so.11.1 libclntsh.so # ln -s libocci.so.11.1 libocci.so
安装oci8扩展:
# pecl install oci8
安装过程中会提示输入ORACLE_HOME的路径,也就是instant所在路径
填写shared,instantclient,/opt/oracle/instantclient即可
最后,修改/etc/php.ini,在其中加入extension=oci8.so,重启apache,这样就OK了。
3、测试
只需要测试一下能不能连上数据库,如果oci_connect没问题的话,其余函数应该也是没有问题的。
<?php $conn = oci_connect('hr', 'passwd', 'orcl'); if (!$conn) { $e = oci_error(); print htmlentities($e['message']); exit; } else{ print "successfully connect to oracle."; } ?>
4、更新:
除了直接使用oci8函数外,还可以使用PEAR中的MDB2库来连接Oracle。
如果不知道PEAR是什么,请看这里:PEAR简介:用PEAR来写你的下一个php程序
关于MDB2,请看这里:http://pear.php.net/package/MDB2/
简单来说,MDB2对PHP内置的原始接口进行了抽象封装,为不同的数据库提供了统一的面向对象接口。MDB2涵盖了多种主流数据库,稳定性也不错。因此,如果喜欢用面向对象的方式写程序,又不想“重复发明轮子”,MDB2是个不错的选择。
这篇文章详细介绍了如何安装使用MDB2以及MDB2的oci8驱动,并且给出了范例程序(Oracle的文档服务很是贴心。不得不承认,还是商业软件的文档支持更好)。如果只想知道如何安装使用MDB2,下面是我的快速参考:
a) 安装PEAR
如果是从本文的第一段一步步走下来的话,那此时已经安装过PEAR了。如果不确定有没有安装过,运行
# yum list | grep php-pear
若输出中包含类似
php-pear.noarch 1:1.4.9-4.el5.1 installed
的信息,那就是已经安装过了。
如果没有,则运行以下命令安装
# yum install php-pear
b) 安装MDB2及MDB2的oci8驱动
PEAR内建了自己的包管理系统,就和yum一样,运行几个命令即可自动化下载安装。
安装MDB2
# pear install MDB2
安装oci8驱动
# pear install MDB2#oci8
安装过程中可能会警告
WARNING: channel “pear.php.net” has updated its protocols, use “channel-update pear.php.net” to update
这是因为PEAR包管理系统的协议升级了,客户端需要升级。按照提示,运行如下命令即可解决这个问题:
# pear channel-update pear.php.net
c) 测试(修改自Oracle例程中的init.inc.php)
<?php require_once 'MDB2.php'; $dsn = array( // The type of database to connect to // OCI8 should be the most common for // connections to Oracle databases. 'phptype' => 'oci8', // Usually this is the database host // to connect to. Since oracle manages // this through connection identifiers, one // must be used here. If this variable is // not set, MDB2 will try to retrieve the // SID through the corresponding environment // variable. 'hostspec' => null, // The username to use when connecting to the // database. 'username' => 'hr', // The corresponding password. 'password' => 'passwd', ); // Establish database connection $db = MDB2::connect($dsn); // Check if the connection was established successfully // using PEAR errorhandling. // More on PEAR error handling can be found here: // http://pear.php.net/manual/en/core.pear.pear-error.php if (PEAR::isError($db)) { die('Could not create database connection. "'.$db->getMessage().'"'); } else{ print "successfully connect to oracle."; } ?>