CVII. Oracle 函数

简介

本类函数使用 Oracle Call Interface(OCI)使用户可以访问 Oracle 10,Oracle9,Oracle8 和 Oracle7 数据库。支持将 PHP 变量与 Oracle 占位符(placeholder)绑定,具有完整的 LOB,FILE 和 ROWID 支持,以及允许使用用户提供的定义变量。

需求

使用本扩展需要 Oracle 客户端库。Windows 用户需要至少版本号为 10 的库才能使用 php_oci8.dll

安装所有所需文件最方便的方法是使用 Oracle Instant Client,可以从此处得到:http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html。要使 OCI8 模块能工作,"basic" 版的 Oracle Instant Client 已经足够。Instant Client 不需要 ORACLE_SID 或 ORACLE_HOME 环境变量被设定。不过可能还是要设定 LD_LIBRARY_PATH 和 NLS_LANG。

在使用本扩展之前,请确认已经为 Oracle 用户和 web daemon 用户正确设置了 Oracle 环境变量。这些变量应该在启动 web server 之前设定。下面列出了需要设置的环境变量:

  • ORACLE_HOME

  • ORACLE_SID

  • LD_PRELOAD

  • LD_LIBRARY_PATH

  • NLS_LANG

对于较少用到的 Oracle 环境变量例如 TNS_ADMIN,TWO_TASK,ORA_TZFILE 和各种 Oracle 全球性设定例如 ORA_NLS33,ORA_NLS10 和 NLS_* 等变量请参考 Oracle 稳当。

在为 web 服务器用户设置环境变量之后,还需要将 web 服务器用户(nobody,www)加到 oracle 组中。

I如果 web 服务器不能够启动或者在启动的时候崩溃: 检查 Apache 是否连接了 pthread 库:

# ldd /www/apache/bin/httpd
    libpthread.so.0 => /lib/libpthread.so.0 (0x4001c000)
    libm.so.6 => /lib/libm.so.6 (0x4002f000)
    libcrypt.so.1 => /lib/libcrypt.so.1 (0x4004c000)
    libdl.so.2 => /lib/libdl.so.2 (0x4007a000)
    libc.so.6 => /lib/libc.so.6 (0x4007e000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

如果 libpthread 没有列出,必需重新安装 Apache:

# cd /usr/src/apache_1.3.xx
# make clean
# LIBS=-lpthread ./config.status
# make
# make install

请注意在像 UnixWare 之类的某些操作系统中,使用 libthread 代替了 libpthread。则 PHP 和 Apache 必须使用 EXTRA_LIBS=-lthread 配置。

运行时配置

这些函数的行为受 php.ini 的影响。

表 1. OCI8 Configuration Options

NameDefaultChangeableChangelog
oci8.privileged_connect"0"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.max_persistent"-1"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.persistent_timeout"-1"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.ping_interval"60"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.statement_cache_size"20"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.default_prefetch"10"PHP_INI_SYSTEMAvailable since PHP 5.1.2.
oci8.old_oci_close_semantics"0"PHP_INI_SYSTEMAvailable since PHP 5.1.2.

以下是配置选项的简要解释。

oci8.privileged_connect boolean

This option enables privileged connections using external credentials (OCI_SYSOPER, OCI_SYSDBA).

oci8.max_persistent int

The maximum number of persistent OCI8 connections per process. Setting this option to -1 means that there is no limit.

oci8.persistent_timeout int

The maximum length of time (in seconds) that a given process is allowed to maintain an idle persistent connection. Setting this option to -1 means that idle persistent connections will be maintained forever.

oci8.ping_interval int

The length of time (in seconds) that must pass before issuing a ping during oci_pconnect(). When set to 0, persistent connections will be pinged every time they are reused. To disable pings completely, set this option to -1.

注意: Disabling pings will cause oci_pconnect() calls to operate at the highest efficiency, but may cause PHP to not detect faulty connections, such as those caused by network partitions, or if the Oracle server has gone down since PHP connected, until later in the script. Consult the oci_pconnect() documentation for more information.

oci8.statement_cache_size int

This option enables statement caching, and specifies how many statements to cache. To disable statement caching just set this option to 0.

注意: A larger cache can result in improved performance, at the cost of increased memory usage.

oci8.default_prefetch int

This option enables statement prefetching and sets the default number of rows that will be fetched automatically after statement execution.

注意: A larger prefetch can result in improved performance, at the cost of increased memory usage.

oci8.old_oci_close_semantics boolean

This option controls oci_close() behaviour. Enabling it means that oci_close() will do nothing; the connection will not be closed until the end of the script. This is for backward compatibility only. If you find that you need to enable this setting, you are strongly encouraged to remove the oci_close() calls from your application instead of enabling this option.

预定义常量

以下常量由本扩展模块定义,因此只有在本扩展模块被编译到 PHP 中,或者在运行时被动态加载后才有效。

OCI_DEFAULT (integer)

Statement execution mode. Statement is not committed automatically when using this mode.

OCI_DESCRIBE_ONLY (integer)

Statement execution mode. Use this mode if you don't want to execute the query, but get the select-list's description.

OCI_COMMIT_ON_SUCCESS (integer)

Statement execution mode. Statement is automatically committed after oci_execute() call.

OCI_EXACT_FETCH (integer)

Statement fetch mode. Used when the application knows in advance exactly how many rows it will be fetching. This mode turns prefetching off for Oracle release 8 or later mode. Cursor is cancelled after the desired rows are fetched and may result in reduced server-side resource usage.

OCI_SYSDATE (integer)

OCI_B_BFILE (integer)

Used with oci_bind_by_name() when binding BFILEs.

OCI_B_CFILEE (integer)

Used with oci_bind_by_name() when binding CFILEs.

OCI_B_CLOB (integer)

Used with oci_bind_by_name() when binding CLOBs.

OCI_B_BLOB (integer)

Used with oci_bind_by_name() when binding BLOBs.

OCI_B_ROWID (integer)

Used with oci_bind_by_name() when binding ROWIDs.

OCI_B_CURSOR (integer)

Used with oci_bind_by_name() when binding cursors, previously allocated with oci_new_descriptor().

OCI_B_NTY (integer)

Used with oci_bind_by_name() when binding named data types. Note: in PHP < 5.0 it was called OCI_B_SQLT_NTY.

OCI_B_BIN (integer)

SQLT_BFILEE (integer)

The same as OCI_B_BFILE.

SQLT_CFILEE (integer)

The same as OCI_B_CFILEE.

SQLT_CLOB (integer)

The same as OCI_B_CLOB.

SQLT_BLOB (integer)

The same as OCI_B_BLOB.

SQLT_RDD (integer)

The same as OCI_B_ROWID.

SQLT_NTY (integer)

The same as OCI_B_NTY.

SQLT_LNG (integer)

Used with oci_bind_by_name() to bind LONG values.

SQLT_LBI (integer)

Used with oci_bind_by_name() to bind LONG RAW values.

SQLT_BIN (integer)

Used with oci_bind_by_name() to bind RAW values.

SQLT_NUM (integer)

Used with oci_bind_array_by_name() to bind arrays of NUMBER.

SQLT_INT (integer)

Used with oci_bind_array_by_name() to bind arrays of INTEGER.

SQLT_AFC (integer)

Used with oci_bind_array_by_name() to bind arrays of CHAR.

SQLT_CHR (integer)

Used with oci_bind_array_by_name() to bind arrays of VARCHAR2. Also used with oci_bind_by_name().

SQLT_VCS (integer)

Used with oci_bind_array_by_name() to bind arrays of VARCHAR.

SQLT_AVC (integer)

Used with oci_bind_array_by_name() to bind arrays of CHARZ.

SQLT_STR (integer)

Used with oci_bind_array_by_name() to bind arrays of STRING.

SQLT_LVC (integer)

Used with oci_bind_array_by_name() to bind arrays of LONG VARCHAR.

SQLT_FLT (integer)

Used with oci_bind_array_by_name() to bind arrays of FLOAT.

SQLT_ODT (integer)

Used with oci_bind_array_by_name() to bind arrays of LONG.

SQLT_BDOUBLE (integer)

SQLT_BFLOAT (integer)

OCI_FETCHSTATEMENT_BY_COLUMN (integer)

Default mode of oci_fetch_all().

OCI_FETCHSTATEMENT_BY_ROW (integer)

Alternative mode of oci_fetch_all().

OCI_ASSOC (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an associative array as a result.

OCI_NUM (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an enumerated array as a result.

OCI_BOTH (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an array with both associative and number indices.

OCI_RETURN_NULLS (integer)

Used with oci_fetch_array() to get empty array elements if field's value is NULL.

OCI_RETURN_LOBS (integer)

Used with oci_fetch_array() to get value of LOB instead of the descriptor.

OCI_DTYPE_FILE (integer)

This flag tells oci_new_descriptor() to initialize new FILE descriptor.

OCI_DTYPE_LOB (integer)

This flag tells oci_new_descriptor() to initialize new LOB descriptor.

OCI_DTYPE_ROWID (integer)

This flag tells oci_new_descriptor() to initialize new ROWID descriptor.

OCI_D_FILE (integer)

The same as OCI_DTYPE_FILE.

OCI_D_LOB (integer)

The same as OCI_DTYPE_LOB.

OCI_D_ROWID (integer)

The same as OCI_DTYPE_ROWID.

OCI_SYSOPER (integer)

Used with oci_connect() to connect as SYSOPER using external credentials (oci8.privileged_connect should be enabled for this).

OCI_SYSDBA (integer)

Used with oci_connect() to connect as SYSDBA using external credentials (oci8.privileged_connect should be enabled for this).

OCI_LOB_BUFFER_FREE (integer)

Used with OCI-Lob->flush to free buffers used.

OCI_TEMP_CLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary CLOB should be created.

OCI_TEMP_BLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary BLOB should be created.

范例

例 1. 基本查询

<?php

$conn
= oci_connect('hr', 'hr', 'orcl');
if (!
$conn) {
  
$e = oci_error();
  print
htmlentities($e['message']);
  exit;
}

$query = 'SELECT * FROM DEPARTMENTS';

$stid = oci_parse($conn, $query);
if (!
$stid) {
  
$e = oci_error($conn);
  print
htmlentities($e['message']);
  exit;
}

$r = oci_execute($stid, OCI_DEFAULT);
if(!
$r) {
  
$e = oci_error($stid);
  echo
htmlentities($e['message']);
  exit;
}

print
'<table border="1">';
while(
$row = oci_fetch_array($stid, OCI_RETURN_NULLS)) {
  print
'<tr>';
     foreach(
$row as $item) {
       print
'<td>'.($item?htmlentities($item):'&nbsp;').'</td>';
     }
     print
'</tr>';
}
print
'</table>';

oci_close($conn);
?>

例 2. 用绑定变量插入

<?php

// Before running, create the table:
//   CREATE TABLE MYTABLE (mid NUMBER, myd VARCHAR2(20));

$conn = oci_connect('scott', 'tiger', 'orcl');

$query = 'INSERT INTO MYTABLE VALUES(:myid, :mydata)';

$stid = oci_parse($conn, $query);

$id = 60;
$data = 'Some data';

oci_bind_by_name($stid, ':myid', $id);
oci_bind_by_name($stid, ':mydata', $data);

$r = oci_execute($stid);

if(
$r)
  print
"One row inserted";

oci_close($conn);

?>

例 3. 将数据插入到 CLOB 列中

<?php

// Before running, create the table:
//     CREATE TABLE MYTABLE (mykey NUMBER, myclob CLOB);

$conn = oci_connect('scott', 'tiger', 'orcl');

$mykey = 12343;  // arbitrary key for this example;

$sql = "INSERT INTO mytable (mykey, myclob)
        VALUES (:mykey, EMPTY_CLOB())
        RETURNING myclob INTO :myclob"
;

$stid = oci_parse($conn, $sql);
$clob = oci_new_descriptor($conn, OCI_D_LOB);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_bind_by_name($stid, ":myclob", $clob, -1, OCI_B_CLOB);
oci_execute($stid, OCI_DEFAULT);
$clob->save("A very long string");

oci_commit($conn);

// Fetching CLOB data

$query = 'SELECT myclob FROM mytable WHERE mykey = :mykey';

$stid = oci_parse ($conn, $query);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_execute($stid, OCI_DEFAULT);

print
'<table border="1">';
while (
$row = oci_fetch_array($stid, OCI_ASSOC)) {
  
$result = $row['MYCLOB']->load();
  print
'<tr><td>'.$result.'</td></tr>';
}
print
'</table>';

?>

可以很容易地访问存储过程,就和从命令行访问一样。

例 4. 使用存储过程

<?php
// by webmaster at remoterealty dot com
$sth = oci_parse($dbh, "begin sp_newaddress( :address_id, '$firstname',
'$lastname', '$company', '$address1', '$address2', '$city', '$state',
'$postalcode', '$country', :error_code );end;"
);

// This calls stored procedure sp_newaddress, with :address_id being an
// in/out variable and :error_code being an out variable.
// Then you do the binding:

   
oci_bind_by_name($sth, ":address_id", $addr_id, 10);
   
oci_bind_by_name($sth, ":error_code", $errorcode, 10);
   
oci_execute($sth);

?>

连接处理

OCI8 扩展提供了 3 个不同函数来连接 Oracle。取决于用户来使用对自己的应用程序最合适的函数。本节的信息有助于用户作出合适的选择。

连接到 Oracle 服务器从所需的时间上来讲是个相当花费的操作。oci_pconnect() 函数使用了一个连接的持久缓冲区,可以被不同的脚本请求重复使用。这意味着通常在每个 PHP 进程(或 Apache 子进程)中只需要连接一次。

如果应用程序连接 Oracle 时对每个 web 用户都使用了不同的认证信息,则由 oci_pconnect() 使用的持久缓冲区就用处不大了,因为随着并发用户的增加,到某个程度后会由于要保持太多的空闲连接而对 Oracle 服务器的整体性能起到逆反的影响。如果应用程序是这样的架构,建议要么用 oci8.max_persistentoci8.persistent_timeout 配置选项(此二者可以使用户控制持久连接缓冲区的大小和生命周期)来协调应用程序,要么用 oci_connect() 来连接。

oci_connect()oci_pconnect() 都使用了一个连接缓冲区。如果在某个脚本中用同样的参数多次调用 oci_connect(),则第二个和之后的调用会返回已有的连接句柄。oci_connect() 使用的连接缓冲区会在脚本执行完毕后或者明确地关闭了连接句柄时被清空。oci_pconnect() 有相似的行为,不过其缓冲区独立地维持着并在不同请求之间都存活着。

要记住此缓冲特性,因为它使两个句柄没有在事务级隔离开来(事实上是同一个连接句柄,因此没有任何方式的隔离)。如果应用程序需要两个独立的,事务级隔离的连接,应该使用 oci_new_connect()

oci_new_connect() 总是创建一个到 Oracle 服务器的新连接,不管其它连接是否已经存在。高流量的 web 应用应该避免使用 oci_new_connect(),尤其是在程序最忙的部分。

驱动程序支持的数据类型

表 2. 用 oci_bind_by_name() 函数绑定参数时支持以下类型

类型映射
SQLT_NTY映射到一个来自 PHP collection 对象的本地 collection 类型,例如由 oci_new_collection() 创建的。
SQLT_BFILEE映射到一个本地的 descriptor,例如由 oci_new_descriptor() 创建的。
SQLT_CFILEE映射到一个本地的 descriptor,例如由 oci_new_descriptor() 创建的。
SQLT_CLOB映射到一个本地的 descriptor,例如由 oci_new_descriptor() 创建的。
SQLT_BLOB映射到一个本地的 descriptor,例如由 oci_new_descriptor() 创建的。
SQLT_RDD映射到一个本地的 descriptor,例如由 oci_new_descriptor() 创建的。
SQLT_NUM将 PHP 参数转换为 C 语言的 long 类型,并绑定为其值。
SQLT_RSET映射到一个本地的 statement 句柄,例如由 oci_parse() 创建或从其它 OCI 查询取得的。
SQLT_CHR 以及任何其它类型将 PHP 参数转换为字符串类型并绑定为字符串。

表 3. 在从结果集中取得列时支持以下类型

类型映射
SQLT_RSET创建一个 oci statement 资源来代表指针。
SQLT_RDD创建一个 ROWID 对象。
SQLT_BLOB创建一个 LOB 对象。
SQLT_CLOB创建一个 LOB 对象。
SQLT_BFILE创建一个 LOB 对象。
SQLT_LNG限制为 SQLT_CHR,返回为字符串。
SQLT_LBI限制为 SQLT_BIN,返回为字符串。
任何其它类型限制为 SQLT_CHR,返回为字符串。
目录
oci_bind_array_by_name -- Binds PHP array to Oracle PL/SQL array by name
oci_bind_by_name -- 绑定一个 PHP 变量到一个 Oracle 位置标志符
oci_cancel -- 取消从游标读取数据
oci_close -- 关闭 Oracle 连接
OCI-Collection->append -- Appends element to the collection
OCI-Collection->assign -- Assigns a value to the collection from another existing collection
OCI-Collection->assignElem -- Assigns a value to the element of the collection
OCI-Collection->free -- Frees the resources associated with the collection object
OCI-Collection->getElem -- Returns value of the element
OCI-Collection->max -- Returns the maximum number of elements in the collection
OCI-Collection->size -- Returns size of the collection
OCI-Collection->trim -- Trims elements from the end of the collection
oci_commit -- 提交未执行的事务处理
oci_connect -- 建立一个到 Oracle 服务器的连接
oci_define_by_name -- 在 SELECT 中使用 PHP 变量作为定义的步骤
oci_error -- 返回上一个错误
oci_execute -- 执行一条语句
oci_fetch_all -- 获取结果数据的所有行到一个数组
oci_fetch_array -- Returns the next row from the result data as an associative or numeric array, or both
oci_fetch_assoc -- Returns the next row from the result data as an associative array
oci_fetch_object -- Returns the next row from the result data as an object
oci_fetch_row -- Returns the next row from the result data as a numeric array
oci_fetch -- Fetches the next row into result-buffer
oci_field_is_null -- 检查字段是否为 NULL
oci_field_name -- 返回字段名
oci_field_precision -- 返回字段精度
oci_field_scale -- 返回字段范围
oci_field_size -- 返回字段大小
oci_field_type_raw -- 返回字段的原始 Oracle 数据类型
oci_field_type -- 返回字段的数据类型
oci_free_statement -- 释放关联于语句或游标的所有资源
oci_internal_debug -- 打开或关闭内部调试输出
OCI-Lob->append -- Appends data from the large object to another large object
OCI-Lob->close -- Closes LOB descriptor
oci_lob_copy -- Copies large object
OCI-Lob->eof -- Tests for end-of-file on a large object's descriptor
OCI-Lob->erase -- Erases a specified portion of the internal LOB data
OCI-Lob->export -- Exports LOB's contents to a file
OCI-Lob->flush -- Flushes/writes buffer of the LOB to the server
OCI-Lob->free -- Frees resources associated with the LOB descriptor
OCI-Lob->getBuffering -- Returns current state of buffering for the large object
OCI-Lob->import -- Imports file data to the LOB
oci_lob_is_equal -- Compares two LOB/FILE locators for equality
OCI-Lob->load -- Returns large object's contents
OCI-Lob->read -- Reads part of the large object
OCI-Lob->rewind -- Moves the internal pointer to the beginning of the large object
OCI-Lob->save -- Saves data to the large object
OCI-Lob->saveFile -- 别名 oci_lob_import()
OCI-Lob->seek -- Sets the internal pointer of the large object
OCI-Lob->setBuffering -- Changes current state of buffering for the large object
OCI-Lob->size -- Returns size of large object
OCI-Lob->tell -- Returns current position of internal pointer of large object
OCI-Lob->truncate -- Truncates large object
OCI-Lob->write -- Writes data to the large object
OCI-Lob->writeTemporary -- Writes temporary large object
OCI-Lob->writeToFile -- 别名 oci_lob_export()
oci_new_collection -- 分配新的 collection 对象
oci_new_connect -- 建定一个到 Oracle 服务器的新连接
oci_new_cursor -- 分配并返回一个新的游标(语句句柄)
oci_new_descriptor -- 初始化一个新的空 LOB 或 FILE 描述符
oci_num_fields -- 返回结果列的数目
oci_num_rows -- 返回语句执行后受影响的行数
oci_parse -- 配置 Oracle 语句预备执行
oci_password_change -- 修改 Oracle 用户的密码
oci_pconnect -- 使用一个持久连接连到 Oracle 数据库
oci_result -- 返回所取得行中字段的值
oci_rollback -- 回滚未提交的事务
oci_server_version -- 返回服务器版本信息
oci_set_prefetch -- 设置预提取行数
oci_statement_type -- 返回 OCI 语句的类型
ocibindbyname -- oci_bind_by_name() 的别名
ocicancel -- oci_cancel() 的别名
ocicloselob -- OCI-Lob->close 的别名
ocicollappend -- OCI-Collection->append 的别名
ocicollassign -- OCI-Collection->assign 的别名
ocicollassignelem -- OCI-Collection->assignElem 的别名
ocicollgetelem -- OCI-Collection->getElem 的别名
ocicollmax -- OCI-Collection->max 的别名
ocicollsize -- OCI-Collection->size 的别名
ocicolltrim -- OCI-Collection->trim 的别名
ocicolumnisnull -- oci_field_is_null() 的别名
ocicolumnname -- oci_field_name() 的别名
ocicolumnprecision -- oci_field_precision() 的别名
ocicolumnscale -- oci_field_scale() 的别名
ocicolumnsize -- oci_field_size() 的别名
ocicolumntype -- oci_field_type() 的别名
ocicolumntyperaw -- oci_field_type_raw() 的别名
ocicommit -- oci_commit() 的别名
ocidefinebyname -- oci_define_by_name() 的别名
ocierror -- oci_error() 的别名
ociexecute -- oci_execute() 的别名
ocifetch -- oci_fetch() 的别名
ocifetchinto -- 获取下一行到一个数组
ocifetchstatement -- oci_fetch_all() 的别名
ocifreecollection -- OCI-Collection->free 的别名
ocifreecursor -- oci_free_statement() 的别名
ocifreedesc -- OCI-Lob->free 的别名
ocifreestatement -- oci_free_statement() 的别名
ociinternaldebug -- oci_internal_debug() 的别名
ociloadlob -- OCI-Lob->load 的别名
ocilogoff -- oci_close() 的别名
ocilogon -- oci_connect() 的别名
ocinewcollection -- oci_new_collection() 的别名
ocinewcursor -- oci_new_cursor() 的别名
ocinewdescriptor -- oci_new_descriptor() 的别名
ocinlogon -- oci_new_connect() 的别名
ocinumcols -- oci_num_fields() 的别名
ociparse -- oci_parse() 的别名
ociplogon -- oci_pconnect() 的别名
ociresult -- oci_result() 的别名
ocirollback -- oci_rollback() 别名
ocirowcount -- oci_num_rows() 的别名
ocisavelob -- OCI-Lob->save 的别名
ocisavelobfile -- OCI-Lob->import 的别名
ociserverversion -- oci_server_version() 的别名
ocisetprefetch -- oci_set_prefetch() 的别名
ocistatementtype -- oci_statement_type() 的别名
ociwritelobtofile -- OCI-Lob->export 的别名
ociwritetemporarylob -- OCI-Lob->writeTemporary 的别名

add a note add a note User Contributed Notes
christopher dot jones at oracle dot com
17-Jun-2007 04:25
There are several good books on PHP and Oracle available - search your favorite bookstore.  There is also a free book from Oracle "The Underground PHP and Oracle Manual" that covers the OCI8 extension: http://otn.oracle.com/tech/php/pdf/underground-php-oracle-manual.pdf
(free registration for OTN required, IIRC). Disclaimer: I'm one of its authors.
tuliogs at pgt dot mpt dot gov dot br
23-May-2007 03:12
Regarding issues with glibc "double free or corruption" or "free(): invalid next size" errors in error_log with PHP4 (PHP 4.4.7 is still afftected by this issue), and in addition to Rainer Kliers notes below, if youre using autoconf 2.5 (default on Redhat ES/CentOS 4.4 and 5, for example), you must delete PHPs "configure" script before running "buildconf --force", or it will do nothing.

After that, youll need to use PHP 5 oci8 syntax with configure:
--oci8=instantclient,/path/to/instantclient

Only after this youll be able to compile PHP, but its a guaranteed fix - and, just to enforce Rainers point (as opposed to what has been said in other places), no need to rise memory limit and edit Makefile on x86-32. Good luck. ;)
david dot reynoldsat at ipl dot com
10-Apr-2007 02:56
I had a problem loading php_oci8.dll with php 5.2, Apache, and windows XP - a module not loaded error, on every apache restart.
I eventually found that I had to add the oracle instantclient library path to the %PATH% under SYSTEM and not under USER.  Doing that, and then rebooting, fixed the error - as Apache is starting as a service (outside the user setup).
James VL
28-Feb-2007 06:49
re: Andrei Kubar

I was using Oracle Instant Client on Windows XP, and was getting the

PHP Startup: Unable to load dynamic library 'C:\php\ext\php_oci8.dll' - The specified module could not be found.

error at startup, even though I had done all (most?) of the PHP and Oracle setup routines.

For me it wasn't the lack of mfc*.dll files, but a simple PATH issue: in addition to defining the environment variable TNS_ADMIN, I had to include my instant client directory in my PATH.
jay dot couture at gmail dot com
06-Dec-2006 11:26
# Here's what it took to get it going for me on Red Hat on
# x86_32 w/ 10gr2 and php5.1.2
# I sincerely appreciate all of the other poster's notes.
# It was a combination of a few
# of them to get mine configured. My note should reflect this:

# install the instantclient basic and sdk like this
# note: the original poster had you install into a lib subdirectory,
# but when I tried this it couldn't find the sdk files. So I moved
# the files in lib into the parent directory as
# shown below. Actually I copied them, YMMV
mkdir -p /usr/lib/oracle/10.2.0.2/client
unzip -jd /usr/lib/oracle/10.2.0.2/client
   instantclient-basic-linux-x86-32-10.2.0.2-20060331.zip
mkdir -p /usr/include/oracle/10.2.0.2/client
unzip -jd /usr/lib/oracle/10.2.0.2/client
   instantclient-sdk-linux-x86-32-10.2.0.2-20060331.zip
ln -s /usr/lib/oracle/10.2.0.2/client/libclntsh.so.10.1
   /usr/lib/oracle/10.2.0.2/client/libclntsh.so

# make the full client use instantclient's files
cd /app/oracle/product/10.2.0/db_1
mv lib oldlib
ln -s /usr/lib/oracle/10.2.0.2/client/lib lib
ln -s /usr/include/oracle/10.2.0.2/client include

#php configure line is:
   ./configure --with-oci8=instantclient,/usr/lib/oracle/10.2.0.2/client

# I had to do this, or the OCI8 would not compile when
# I ran make on PHP5.1.2 I did not do this originally when I
# had the files in the lib sudirectory (see my note above) so
# that may be the true issue.
export LD_LIBRARY_PATH=/usr/lib/oracle/10.2.0.2/client:$LD_LIBRARY_PATH

make

make install

#In apache2 edit the envvars and add
LD_LIBRARY_PATH="/usr/local/apache2/lib:
   /usr/lib/oracle/10.2.0.2/client:$LD_LIBRARY_PATH"
TNS_ADMIN="/usr/lib/oracle/10.2.0.2/client"
LANG=en_US
export LD_LIBRARY_PATH LANG TNS_ADMIN

#Restart Apache

Jay
Andrei Kubar
26-Nov-2006 03:53
If you try to use it with Oracle Instant Client 10.2.0.2 on Windows 2003 Server, you might be getting the

PHP Startup: Unable to load dynamic library 'C:\php\ext\php_oci8.dll' - The specified module could not be found.

error at startup, even though you had all done corresponding to PHP and Oracle setup routines.

reason for this may be the lack of

<b>mfc71.dll , msvcrt.dll and msvcr71.dll</b>

libraries on the system. Particularly the msvcr71.dll was the one which I missed and which caused the startup problem.

It is also a good idea to install the Patch 9 for the instant client (patch number 5604010 in metalink), it contains updated oci8.dll and oraociei10.dll versions.
private at private dot com
05-Jun-2006 04:59
To fsegtrop at estiem dot org:

Thank you for the note about the DOS/Unix line-endings.  My boss gave me his copy of tnsnames.ora from his Windows machine for my use on my Linux workstation.  I spent three hours trying to figure out why, and researching Oracle connections.

A simple dos2unix command on my tnsnames.ora file fixed the problem.
rainer dot klier at gmx dot at
22-May-2006 09:08
estoreic (note from 15-May-2006 10:54) is right.

there seems to be a problem with the oci8-api-functions in php 4.4.x.

there are error-messages like these in the error_log:
child pid 22297 exit signal Segmentation fault (11)
*** glibc detected *** double free or corruption (out): 0x00000000019f4730 ***
*** glibc detected *** double free or corruption (!prev): 0x0000000001111d90 ***
*** glibc detected *** corrupted double-linked list: 0x0000000001111d50 ***

using php 4.4.x with oracle 10.x is impossible, until you do the following:
1. download latest oci8-package from http://pecl.php.net/package/oci8
2. extract package somewhere
3. go to php-4.4.x-source directory
4. rm -rf ext/oci8
5. cp extraceted oci8-1.2.x directory to/as ext/oci8
6. make distclean
7. ./buildconf --force
8. ./.configure (with the options you need)
9. make
10. only for x86_64:
create pear-install.ini:
-----------------------------------------------
[PHP]

memory_limit = 128M      ; Maximum amount of memory a script may consume (8MB)
------------------------------------------------

11. edit Makefile:
replace:
PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0
with:
PEAR_INSTALL_FLAGS = -cpear-install.ini -dshort_open_tag=0 -dsafe_mode=0

12. make install

have fun!
oracle connections will work now!
estoreic dot list at gmail dot com
16-May-2006 05:54
We were having performance issues caused by Segmentation Faults on pages using Oracle.

An example of the Seg faults appearing in Apache's error log is:
*** glibc detected *** free(): invalid next size (fast): 0x0969ef30 ***
[Mon May 08 09:41:51 2006] [notice] child pid 3065 exit signal Aborted (6)

OR

[Mon May 08 09:48:58 2006] [notice] child pid 4747 exit signal Segmentation fault (11)

Our issue was due to a problem with OCI8 module in PHP (latest version 4.4.2).

Our solution involved recompiling PHP with the latest PECL OCI8 extension which can be downloaded from:
http://pecl.php.net/package/oci8

All segmentation faults and performance issues stopped once PHP was recompiled with OCI8 1.2.1.

If you are experience performance issues and/or seg faults I would recommend recompiling PHP with the latest stable OCI8 extension.
terry dot greenlaw at logicalshift dot com
12-May-2006 05:10
Dropping support for Oracle 9i clients on Windows is a huge mistake! Most people in production environments can't just slap another oracle_home on their box just for php traffic.

The Instant Client is aimed at desktop users, not servers, and is the last thing an experienced Oracle person would be installing.

The code works fine in 5.1.3RC2, so I guess we're stuck on that version until the issue is addressed properly.
jon at cssofla dot com
10-May-2006 04:48
For installation and enabling support of OCI8, I highly recommend Zend Core for Oracle from Zend.  I had almost a month's worth of trouble trying to get OCI8 working until I found that, and it was a piece of cake with that.
f dot kheiri at ucl dot ac dot uk
29-Apr-2006 02:40
To compile PHP 4.4.2 with OCI8 / Oracle 9i / AIX 5.2 (64-bit) / GCC

PHP will automatically compile against the Oracle 64-bit libraries, which PHP being a 32-bit app, will cause "make" to fail (though it will configure fine). Here's how to avoid this:

1. replace your PHP's ext/oci8 directory with the latest ext/oci8 directory downloadable from PECL - then remove the old directory entirely

2. rebuild configure by running:

./buildconf --force

...in PHP's root directory. This will rebuild the configure script.

3. using a tool like sed, in your configure file replace all instances of /path/to/oracle/lib with /path/to/oracle/lib32 - note, this may require GNU's autoconf, m4 and gnumake.

4. export LD_LIBRARY_PATH=/path/to/oracle/lib32

5. ./configure --with-oci-8=/path/to/oracle (and any other options)

Then, the usual make and make install.
25-Apr-2006 10:29
# here's what it took to get it going for me on rhel4 on x86_64 w/ 10gr2 and php5.0.5
# hopefully this will save someone a little grief
# first you must install the 10.2 full client in /app/oracle/product/10.2.0/db_1
# follow all the instructions. This part will be a bitch.

# install the instantclient basic and sdk like this
mkdir -p /usr/lib/oracle/10.2.0.2/client/lib
unzip -jd /usr/lib/oracle/10.2.0.2/client/lib instantclient-basic-linux-x86-64-10.2.0.2-20060228.zip
mkdir -p /usr/include/oracle/10.2.0.2/client
unzip -jd /usr/lib/oracle/10.2.0.2/client instantclient-sdk-linux-x86-64-10.2.0.2-20060228.zip
ln -s /usr/lib/oracle/10.2.0.2/client/lib/libclntsh.so.10.1 /usr/lib/oracle/10.2.0.2/client/lib/libclntsh.so

# make the full client use instantclient's files
cd /app/oracle/product/10.2.0/db_1
mv lib oldlib
ln -s /usr/lib/oracle/10.2.0.2/client/lib lib
ln -s /usr/include/oracle/10.2.0.2/client include

php configure line is: --with-oci8=/app/oracle/product/10.2.0/db_1/
jdstil at nononsense dot bluewin dot ch
18-Mar-2006 11:02
Apache 1.3, Oracle 9.2, PHP 5.1.2 on Windows XP Pro.
Very weird behavior with php_oci8.dll coming with the full windows build (I downloaded yesterday...). Couldn't get any of the examples to work, it appears Apache crashes on oci_parse, but not so if I program "C style":

  while this doesn't work:
   <?php
     $db_conn
= oci_connect("scott","tiger");
    
$parsed = oci_parse($db_conn,"select * from emp"); <-- Apache crashes on execution of this statement
    
// etc...
  
?>

  this does:
   <?php

    
function main($connection)
     {
      
$parsed = oci_parse($connection,"select * from emp");
      
$r = oci_execute($parsed, OCI_DEFAULT);
      
// etc...
    
}

    
$db_conn = oci_connect("scott","tiger");

    
main($db_conn);

    
oci_close($db_conn);
  
?>

Took me the whole day, then I found Francesco Marsan's note (THANKS!) dated February 9th, 2006... and indeed, downloading from http://pecl4win.php.net/ext.php/php_oci8.dll solved the problem instantly.
soef at tjah dot net
03-Mar-2006 08:04
To install this in gentoo linux you will need to do some weird stuff:

-  Make sure you have this use flags set: "dba cli pcre xml zlib oci8-instant-client"
- Unmask PHP (5.1.1) by placing "dev-lang/php ~x86" in /etc/portage/package.keywords
- Unmask oracle-instantclient-basic (10.2.0.1-r1) by placing "dev-db/oracle-instantclient-basic ~x86"
- Download oracle files from "http://otn.oracle.com/software/tech/ oci/instantclient/htdocs/linuxsoft.html" (You have to make an account and login, in order to download the packages:

   * instantclient-basic-linux32-10.2.0.1-20050713.zip
   * instantclient-sdk-linux32-10.2.0.1-20050713.zip

- Place the downloaded packages in "/usr/portage/distfiles"
- "emerge apache dev-lang/php5" (If you done right, the build for the instantclient will be selected automaticly.
- Configure your "/etc/conf.d/apache2" to make sure you have "-D PHP5" in your "APACHE_OPTS"
dfischer at qualcomm dot com
03-Mar-2006 01:00
Here are some tips on getting the instant client to work with php:

I am using Fedora Core 3 and php-5.1.2 on x86.

Install:
oracle-instantclient-basic-10.xxxx.i386.rpm
oracle-instantclient-devel-10.xxxx.i386.rpm

Configuring php:
./configure --with-oci8=instantclient,/usr/lib/oracle/10.xxx/client/lib/
This path will change if you unzip it isntead of using the rpms. Make sure it points to where libclntsh.so is installed.

Configuring apache:
The following lines need to be in your .../apache/bin/envvars file:
LD_LIBRARY_PATH="/usr/lib/oracle/10.xxx/client/lib/: /opt/apache2/lib:$LD_LIBRARY_PATH"
TNS_ADMIN="/usr/lib/oracle/10.1.0.4/client/lib/"
LANG=en_US
export LD_LIBRARY_PATH LANG TNS_ADMIN
You will need to modify the paths to the oracle instantclient libs and to apache. In addition, the language will need to be modified if not US English.

TNS Names and Oracle:
Put the tnsnames.ora and sqlnet.ora files into the same directory as libclntsh.so.

Restart apache and you should be able to connect.
jnavratil at houston dot rr dot com
13-Feb-2006 01:30
The error message "There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory" is somewhat deceptive in that it can be emitted even when ORACLE_HOME is correctly set, but that there is a connection failure when the OCI8 extension uses the Oracle OCI API.  This API requires access to several files in the Oracle distribution which, at least in the 10g release 2 distribution, are not available to 'others'.  It seems this may be the reason that we are directed to give oracle 'oinstall' group access to the apache user.  For those who do not consider this a good idea, the solution is to grant 'other' access to the files.

I used the following script (YMMV) ....

export ORACLE_HOME=<your-Oracle-home-here>
chmod o=x $ORACLE_HOME/network
chmod o=x $ORACLE_HOME/network/admin
chmod o=r $ORACLE_HOME/network/admin/tnsnames.ora
chmod o=r $ORACLE_HOME/nls
chmod o=r $ORACLE_HOME/nls/data
chmod o=r $ORACLE_HOME/nls/data/*
chmod o=x $ORACLE_HOME/oracore
chmod o=x $ORACLE_HOME/oracore/zoneinfo
chmod o=r $ORACLE_HOME/oracore/zoneinfo/timezlrg.dat
chmod o=r $ORACLE_HOME/rdbms
chmod o=r $ORACLE_HOME/rdbms/mesg
chmod o=r $ORACLE_HOME/rdbms/mesg/*

The ORACLE_HOME environment variable *IS* required, but I found no need to set the others (again, YMMV).

To discover the files referenced by your OCI8 scripts, you can open the security by giving apache group access to the Oracle directories, touching some temp file and using 'find' to discover the files which have been accessed.  Try using...

cd $ORACLE_HOME
find . -anewer <my-touched-temp-file> -print
francesco [dot] marsan [at] yahoo.it
09-Feb-2006 09:47
If you experience Apache crashes on a Windows platform with PHP 5.1.2 while trying to access Oracle, try exchanging the php_oci8.dll that comes with the distribution, with the one that is on http://pecl4win.php.net/ext.php/php_oci8.dll. After much trouble while trying many install options this finally solved my issues and worked fine.
cjbj at hotmail dot com
20-Jan-2006 04:09
PHP 5.1.2 was the first PHP release to ship the "re-factored" OCI8 1.1 driver.

The configuration options for the re-factored driver have changed, particularly for building with Oracle Instant Client. Some older articles and documentation are now obsolete.  Run ./configure --help to see the new syntax.

User's of PHP prior to 5.1.2 can install the re-factored driver from http://pecl.php.net/package/oci8 or http://pecl4win.php.net/ext.php/php_oci8.dll
wes9999 at myfastmail dot com
18-Jan-2006 05:19
If you're compiling php 5.1.2, and using the oracle instant client, the appropriate configure option is:
--with-oci8=instantclient,/path/to/instantclient/libs

which is a change from the configure option for php 5.1.1, which was:
--with-oci8-instant-client=/path/to/instantclient/libs

If you use the old one with php 5.1.2, it just silently ignores this option and the resulting php build doesn't have oracle support.
scoop at subindie dot com
26-Oct-2005 08:27
Regarding compiling with the recently updated OCI8 Extension (http://pecl.php.net/package/oci8).

I ran into problems when statically compiling, such as numerous "undefined reference to `zif_oci_***'" errors.  Since I likely won't be the only one to run into this problem, here's some helpful hints:

If you've previously compiled your php installation, first: make clean

Then replace the existing php-x.x.x/ext/oci8 directory with the latest package from: http://pecl.php.net/package/oci8

./buildconf --force
./config ..
make
jistanidiot at gmail dot com
16-Sep-2005 03:07
On RHEL for PHP4 or 5...

For Oracle 9i before you compile PHP but after you install Oracle, you need to make the following symlinks:

ln -s $ORACLE_HOME/rdbms/public/nzerror.h  $ORACLE_HOME/rdbms/demo/nzerror.h

ln -s $ORACLE_HOME/rdbms/public/nzt.h $ORACLE_HOME/rdbms/demo/nzt.h

ln -s $ORACLE_HOME/rdbms/public/ociextp.h $ORACLE_HOME/rdbms/demo/ociextp.h

ln -s $ORACLE_HOME/lib/libclntsh.so.9.0 $ORACLE_HOME/lib/libclntsh.so.8.0

ln -s $ORACLE_HOME/oui/bin/linux/libcdlntsh.so.9.0
$ORACLE_HOME/oui/bin/linux/libcdlntsh.so.8.0

With 10g you need to make the first three and then this one:
ln -s $ORACLE_HOME/lib/libclntsh.so.10.0 $ORACLE_HOME/lib/libclntsh.so.8.0
denis dot delamarre at chu-rennes dot fr
10-Jun-2005 05:00
php5 + Apache 2 + solaris 2.10 + oracle9i (64bits)

'./configure' '--with-oracle=/prod/dba/oraeve/ora9i' '--with-apxs2=/usr/local/apache2/bin/apxs' '--with-zlib' '--with-gd' '--without-mysql' '--with-oci8=/prod/dba/oraeve/ora9i'

fail with :
ld: fatal : fichier libclntsh.so : wrong elf class : ELFCLASS64

the solution is between ./configure and make command to edit Makefile and replace /ora9i/lib  with  /ora9i/lib32

all it's ok
MSapp
07-Jun-2005 01:48
Problems compiling 5.0.4 with Oracle Instant Client 10? (i.e. cannot find -lirc)

Remove the "-lirc" from sdk/demo/sysliblist and rerun configure.
darkstar_ae at hotmail dot com
26-Apr-2005 05:39
When fetching associative arrays, use uppercase string indices. It appears the PHP OCI Library is less lenient with the field names returned by Oracle.

e.g.

echo $row['field1']; // This won't return anything.

as opposed to:

echo $row['FIELD1'];
kucerar at hhmi dot org
23-Feb-2005 04:29
Great Solaris patch!  Finally built.  Here's some tips on connecting:

Just made this on solaris8 32bit, actually works.

1) put everything in one directory
2) unsetenv ORACLE_HOME
3) set the env vars LD_LIBRARY_PATH and SQLPATH and TNS_ADMIN(if you have it) to that directory.
4) use one of the other easy connection notations here

http://www.oracle.com/technology/
docs/tech/sql_plus/10102/readme_ic.htm

These env vars worked when put at the top of apachectl script as well.

To build you may have to fake it out with an ORACLE_HOME var,  but unset it later.  You may also have to fake out the build by putting header files where it is looking for them,  e.g. in the rdbms/demo directory or some such other place.

When running though,  make sure you have only the files required in only one directory.

Oracle has not put up a link to the 32bit solaris sqlplus--you have to guess it--it's there though:

http://download.oracle.com/otn/solaris/instantclient/
instantclient-sqlplus-solaris32-10.1.0.3.zip
 
...and don't forget to add ".world" on to the end of your SID. It's very common to have to specify DBNAME.WORLD to connect.
buswash at gmail dot com
02-Feb-2005 02:51
PHP 5.0.3 + Solaris 9 (UltraSPARC) + Apache 2.0.51 + Oracle 10g Instant Client 10.1.0.3

Thanks to Jakob's patch I got this combination working.  Here are some things that helped me:

1. After getting this:
ld: fatal: file /opt/oracle/instantclient/libclntsh.so: wrong ELF class: ELFCLASS64

I realized that PHP is a 32-bit application and that all 3rd-party libraries need to be 32-bit as well.  You need to download the 32-bit version of Instant Client (basic + sdk), even if you are running the 64-bit Solaris OS.

2. My patch command syntax was a little different:
patch -p0 -i php5_ociclient.patch config.m4

Thanks again to Jakob for porting the patch over to PHP 5.

Marc
jakob dot jellbauer at interhyp dot de
19-Jan-2005 08:00
Yes, i`ve made it !
Installing PHP 5.0.3 and the Oracle 10g Instant Client on Linux .

There is no need to have a full Oracle Installation on the Webserver, you only need the client.

http://www.oracle.com/technology/pub/notes/technote_php_instant.html

The patches provided from Oracle are for PHP Versions 4.3.9 or 4.3.10.

Here is the handmade patch for PHP 5.0.3 :

...
patch -u php-5.0.3/ext/oci8/config.m4 php5_ociclient.patch
cd php-5.0.3
rm -rf autom4te.cache config.cache
./buildconf --force
...

Download the Patch here:

 http://www.pubanz.de/jakob/php5_ociclient.zip

Have fun,

Feel free to ask me if there are any questions
mark at magpies dot net
06-Jan-2005 09:05
Hello once again.
This time I present details on how to get Oracle Instant Client 10g ( 10.1.0.3 ), PHP 5.0.3 and Apache 2.0.52 running together on Linux (I've used fedora core 1 but I can't see why this will not work for any other distro )
*Note* This is not a guide on compiling php and httpd there are plenty of guides around to do that. This just covers compiling and using the oci8 module with php.

1. Set-up and install apache-2.0.52 as per normal

2. Unpack the Oracle 10g Instant Client ( 10.1.0.3 SDK + Basic, I also use the sqlplus pack to test the connection outside of apache / php )
  rpm -ivh oracle-instantclient-basic-10.1.0.3-1.i386.rpm  oracle-instantclient-devel-10.1.0.3-1.i386.rpm  oracle-instantclient-sqlplus-10.1.0.3-1.i386.rpm

3. Set env ORACLE_HOME to the clients path in the current shell your shell command may vary (this is bash )
  export ORACLE_HOME=/usr/lib/oracle/10.1.0.3/client; export LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.3/client/lib;
(if you want to test if you can now get a connection to oracle using sqlplus see item 10 below.)

4. Unpack php-5.0.3 as per normal add in  --with-oci8  to the configure options. If the ORACLE_HOME is set previously then adding the directory as per "--with-oci8=$ORACLE_HOME" should not be necessary. Do this to be safe though.

5. Run the ./configure program in php source directory. Don't make it just yet though.

6. The compiler needs to find the includes oci.h + others so, from the default client install dirs, I needed to edit the php Makefile after it was configured. Open it up and look for "EXTRA_INCLUDES" and add to end of line
-I/usr/include/oracle/10.1.0.3/client  (thats a capital i ) save the Makefile, then finish off compiling and installing php.  Please note im sure this will be changed in php's configure so it finds these by default in the not too distant future.

7. Create a directory /etc/oracle and place your tnsnames.ora file in there, (VERY IMPORTANT make sure you chmod your tnsnames.ora to ensure that whatever username your httpd server runs under can read the file (1.5 hours of frustration later i figured this out). I just did "chmod 0644 tnsnames.ora" it doesn't matter where you put this as long as you set the env  TNS_ADMIN to it. (IMPORTANT  TNS_ADMIN points to a directory not the actual tnsnames.ora file )

8. My system uses a /etc/init.d/httpd script to start up httpd so in that file I exported the ORACLE_HOME & TNS_ADMIN env vars before the httpd is run, oh you will need to set LD_LIBRARY_PATH as well if you not added the path to ld.so.conf
  export ORACLE_HOME=/usr/lib/oracle/10.1.0.3/client; export TNS_ADMIN=/etc/oracle
 
9. start httpd and bobs your uncle....

10. You can test connection once the instant client rpm's are installed by using  sqlplus.  set  ORACLE_HOME as above,  TNS_ADMIN as above, LD_LIBRARY_PATH as above and if necessary.  Then  sqlplus <username>/<password>@<sid or service_name as per tns_admin file>  use sqlplus here as you would normally

Mark
PS: Thanks Oracle for the SDK,  about time !
Mark at catalyst dot net dot nzed
10-Aug-2004 03:28
ReCompiling PHP4 to have oracle 8 support (oci8) on Debian Linux, using the Oracle 10g client libraries. Log in as root.

PACKAGES REQUIRED:
php4-dev
php4 (source files)
php4 module (might not be required, but it's what i had installed at the time)

OTHER PACKAGE REQUIREMENTS:
Oracle Client Libraries (i used Oracle 10g Server, but you should be able to use, as has been previously said, any set of the oracle client libraries from 8i onwards).
* make sure this is installed before recompiling php4.

ENVIRONMENT REQUIREMENTS:
- export ORACLE_HOME=[where u installed the oracle client]
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
- export LD_PRELOAD=libclntsh.so.10.1 (the version number at the end will correspond to the oracle version you previously installed. in my case, 10g is 10.1).
- vi /etc/ld.so.conf and add $ORACLE_HOME/lib to the list of paths.
then * run ldconfig to reload those changes to the system * (p.s. make sure it's the full path, and not using any environment variables. e.g. /u01/app/oracle/product/10gRDBMS is my ORACLE_HOME).

STEPS:
- cd /usr/src/[PHP4 Version]
in my case, [PHP4 Version] = php4-4.3.8, so path was
/usr/src/php4-4.3.8

- vi debian/rules
these are the default compilation rules for php4. Find section labeled COMMON_CONFIG = [...] and add --with-oci8 (it should be near the top of the file).

- debchange -i (allows you to edit the change log for the versions of php. btw - you should be in the php4 source code directory). give the version id something obviously unique. don't forget to add a comment.

when all is in readyness, then you should be able to go debian/rules binary to build the debian packages required.
the deb packages are built into the /usr/src directory. and depending on the default compilation options u choose, there should be a few. find the deb package that corresponds to the main php4 module (php4_4.3.8-4.mark.1_i386.deb for me), and run dpkg -i [package name] to install it.

- vi /etc/init.d/apache and add exports for $ORACLE_HOME, $LD_PRELOAD and $LD_LIBRARY_PATH

* don't forget to restart apache /etc/init.d/apache to reload the php4 module. *

IF YOU GET... :
if you get an error saying something about apache cannot load libclntsh.so.10.1, file not found, check the environment variables, for both the user, and in /etc/init.d/apache and also check ld.so.conf to make sure the $ORACLE_HOME/lib path is in there, and has been reloaded (with ldconfig).

editing ld.so.conf was the part that finally got it working for me.
as you should be able to tell, the steps are pretty much the same as for all oracle versions 8i onwards, and all linux OS's. but with a few debian specific paths and commands thrown in.
mark at magpies dot net
05-Jul-2004 04:07
For those trying to use the Oracle Instant Client 10g in a win32 environment, heres a nice easy howto. If you fully read the docs properly and understand what your reading you will be able to set it up, but if like me you want a quick easy fix, heres how I did it.

1. Download and install the Oracle Instant Client to where ever (lets say  c:\ora\client  )
2. Add your connect info, copy a previously created or provided tnsnames.ora file to the above directory.
3. Change Path in the Environment Variables area to add this directory to the path. ie.  c:\ora\client;%SystemRoot%;<and so on>
4. Open regedit and add a Key called ORACLE to HKEY_LOCAL_MACHINE\SOFTWARE
5. To the ORACLE key add a string value called TNS_ADMIN and assign it the directory above (ie. c:\ora\client )  So you end up with KEY_LOCAL_MACHINE\SOFTWARE\ORACLE\TNS_ADMIN = c:\ora\client
6. Set php to use Oci8 extension and bobs your uncle
7. Reboot.

Option 7 was required as the oci8 extension or php wouldn't pick up the path change. Also my problem was how to use other programs like sqlplus without creating extra Environment Variables etc the TNS_ADMIN / tnsnames.ora part makes that simpler and allows you to call things the same as you would before.

PS: This should apply to all the Instant Clients. I haven't tried it with any others but 10g though.

Hope this helps.
beckman at purplecow dot com
14-Jun-2004 11:20
For those of you running Oracle on Linux, and running a remote box also on Linux, here's an easy way to get OCI8 working without having to install the whole Oracle DB just to get your client working.

[PS -- For the life of me, installing client libraries for Oracle really shouldn't be this hard, but it really truly is.]

Step 1.  Copy the following directories from your ORACLE_HOME directory where Oracle is installed (the database server) to your remote client server/machine:

     lib, network, ocommon, plsql, rdbms, oracore

   These contain all of the files/folders/libraries you'll need to compile OCI8 into PHP.  I put this in /home/beckman/oracle and set ORACLE_HOME as that dir.

Step 2.  Compile PHP with --with-oci8=/home/beckman/oracle (obviously using your directory, not mine).  Install, (re)start apache.

Step 3. Remove plsql and rdbms directories from ORACLE_HOME on your remote server, leaving you with lib, network, ocommon and oracore.

Step 4. Read: http://otn.oracle.com/tech/opensource/php/php_troubleshooting_faq.html

NOTE: This will only help you if you (a) have Oracle successfully running on Linux (was RH Enterprise 3 for me) and your client box is running the same OS.  I'm not sure it will work on earlier versions, but it may.  Your results should be posted here methinks!
cyrill@_malevanov_dot_spb_dot_ru
10-May-2004 08:05
Passing CLOB to stored procedure and retrieve CLOB too (function lobinout(a in clob) return clob)

<?
   error_reporting
(1+2+4+8);
  
$conn = OCILogon('batdtd', 'batdtd', 'batxml');
  
  
$lobin = OCINewDescriptor($conn, OCI_D_LOB);
  
$lobout = OCINewDescriptor($conn, OCI_D_LOB);
  
  
$stmt = OCIParse($conn, "declare rs clob; begin :rs := lobinout(:par); end;");
  
$lob_data = 'abcdefgh';
  
   echo
"binding lobin...";
  
OCIBindByName($stmt, ':par', $lobin, -1, OCI_B_CLOB);
  
   echo
"done<br>binding rs...";
  
  
OCIBindByName($stmt, ':rs', $lobout, -1, OCI_B_CLOB);
  
   echo
"done<br>writing temp lob...";
            
// here we pass data to func
  
$lobin -> WriteTemporary($lob_data);
   echo
"done<br>executing...";
  
  
OCIExecute($stmt, OCI_DEFAULT);
            
// here we load data returned from func
  
echo "done<br>rs = ".$lobout->load();
  
OCICommit($conn);
  
$lobin -> free();
  
$lobout -> free();
  
OCIFreeStatement($stmt);
  
OCILogoff($conn);
?>
dadarden_nospamoladude at iti2 dot net
13-Mar-2004 01:27
PHP Oracle -- Compiling Oracle Support into PHP, Apache 2
Apache 2.0.48,  Php 4.3.4,  Red Hat Linux 9.0,  Debian 3.0,  Oracle 9i R2
Dave Darden  1/17/04 -- www.dardensystems.com

First install Apache 2 from source.  Instructions are at http://httpd.apache.org/docs-2.0/install.html. 
I used a --prefix=/usr/local/apache on the install. 

Install Oracle.  There is a very good Oracle install to RedHat 9.0 white paper at http://www.dizwell.com/ that goes step by step through the problems (Oracle is not supported on RedHat 9.  Oracle only supports installation on paid versions of Red Hat). 

If only an Oracle client is installed on the web server (if the database is on another machine in a multi-tier configuration) then you must install both the client and the Oracle Call Interface (OCI).  I think SQLPlus also needs to be installed.  Oracle Network Utilities and Installation Common Files were also installed.  If you cannot configure/make php because of missing Oracle library errors during configure/make, then investigate whether you have installed enough of the client pieces of Oracle on the web server machine. 

I also included a link from  libclntsh.so.8.0  to  libclntsh.so.9.0  in the $ORACLE_HOME/lib directory.  Some internet posts suggested it to prevent errors in php configure/make.  A later experience moving from RedHat to Debian confirms that it is necessary to avoid a make error on a missing lclntsh file. 

In transferring the client software from a Red Hat 9.0 web server installation to a Debian 3.0 (kernel 2.4.18) web server installation I was able to simply copy over the Oracle /u01 directory tree without rerunning the Oracle client installation.  This must be done before php is configured and compiled on the Debian machine so the oci8 libraries are available.  And of course the tips on libclntsh and environment variables must be observed as well. 

Get the php source.  This php configure line worked for me, creating an Apache 2 module, and keeping mysql and gd support.  Add other options if you need them for a given site.  For some reason, even though gd is included with php now, zlib was needed to successfully configure and make php from source when including gd.  You will need to substitute appropriate directory locations for your install of Apache, zlib, and Oracle.

./configure --with-apxs2=/usr/local/apache/bin/apxs \
--with-mysql --with-gd \
--with-zlib-dir=/usr/local \
--with-config-file-path=/etc \
--enable-force-cgi-redirect --disable-cgi \
--with-oci8=/u01/app/oracle/9i --enable-sigchild

Use an absolute path on  -with-oci8=/u01/app/oracle/9i 
(Do not use the $ORACLE_HOME path variable in the configure statement.  For some reason it does not work even when it is set properly.)

Also, set the environment variables in
/usr/local/apache/bin/envvars like so (your env var values should vary):

export ORACLE_SID="lx92"
export ORACLE_HOME="/u01/app/oracle/9i"
export TNS_ADMIN="/u01/app/oracle/9i/network/admin"
export LD_LIBRARY_PATH="/u01/app/oracle/9i/lib"
export TNS_ADMIN="/u01/app/oracle/9i/network/admin/tnsnames.ora"
export TWO_TASK="/u01/app/oracle/9i/network/admin/tnsnames.ora"
export NLS_LANG="English_America.WE8ISO8859P1"
export ORACLE_BASE="/u01/app/oracle"
oddbec_no_more_spam_kthx at online dot no
24-Feb-2004 04:49
I had trouble with norwegian characters using oracle 8.7.1 / php 4something and Apache 2.

The only trouble was that '?' appeared instead of the norwegian characters.

The solution to it all was to add this to the apachectl script:

export NLS_LANG="norwegian_norway.WE8ISO8859P1"
export ORACLE_BASE="/home/oracle"
export ORA_NLS33="/home/oracle/ocommon/nls/admin/data"
export ORACLE_TERM="ansi"
export ORACLE_HOME="/home/oracle"
export LANG="no_NO"

I'm not sure if all of these are necessary, but I took no change, and it works now :)
lomax at arizona edu
25-Jul-2003 11:26
Can't compile php with Oracle 9i and apache on Solaris8?
Sun 280R

Using some of the tips below I had to add this:
(static build)

#!/bin/tcsh
setenv LDFLAGS -L$ORACLE_HOME/lib32

cd php-4.x.x/
./configure --with-oci8=$ORACLE_HOME --with-apache=/path/to/apache_src ..etc
make
make intsall

cd apache_src
(make sure environment variable is still set)
./configure  "--prefix=/usr/apache" "--enable-module=so" \
"--activate-module=src/modules/php4/libphp4.a"  ...etc
make
make install

Having the gcc compilier build php against oracle 32 bit libraries was the key, but without setting LDFLAGS the compiler defaults to using the 64-bit oracle libraries which cause the famous
"...wrong ELF class: ELFCLASS64.." on startup.

The only diffenece here was I didn't have to do play musical directories for it to work. The below post was instrumental in helping me to get this fixed. Thanks to "lore_giver at lycos dot co dot uk"
lore_giver at lycos dot co dot uk
20-May-2003 06:42
Running Oracle 9i on a
Solaris 9 (64 bit) platform with a Sun Server E250:
Apache version 1.3.27
PHP version 4.3.1

I was first getting "...wrong ELF class: ELFCLASS64.."
while doing a ./configure with the --with-oci8 and --with-oracle parameters.

After some unsuccessfull searched I renamed the $ORACLE_HOME/lib to $ORACLE_HOME/lib.org and then renamed the
$ORACLE_HOME/lib32 to $ORACLE_HOME/lib

Thereafter it went passed this config, but now failed on
not being able to find a libwtc9.so file which was in the
$ORACLE_HOME/lib directory  (this message was displayed in the debug.log in the php source directory).

After setting the Environment variable:
LD_LIBRARY_PATH=$ORACLE_HOME/lib
I was able to compile without any errors and 'make' and 'make install' ran smoothly.

I only had to add the php type in the httpd.conf (in your apache conf directory eg. /usr/local/apache/conf)..
AddType application/x-httpd-php .php
to get the php to work again...

I had to then reverse the $ORACLE_HOME/lib swop on top since php was now having problems with the 32 bit version of the library...so switched it back to 64 and my php script worked....

Hope this helps some out there with similar problems..

Cheers
09-Dec-2002 09:53
Configuring/Compiling PHP as a DSO with Oracle support from source on a Sun Solaris 8 box.  We had already installed Oracle 9.2.0 client tools.

1. Make sure the following tools are installed

   autoconf
   automake
   bison
   flex
   gcc
   make
   gzip
  
   They can be downloaded from http://www.sunfreeware.com.
  
2.  Make sure Apache is installed with DSO support.  We ran the Apache configure/compile like so:

   LIBS=-lpthread ./configure \
   --prefix=/usr/local/apache \
   --enable-module=most \
   --enable-shared=max
  
  
   make
   make install
  
3.  If you haven't already, install the Oracle client tools.
4.  Make sure the following environment variables are set correctly and are accessible by all users.  We set them in /etc/profile.

   ORACLE_HOME
   ORACLE_BASE
   NLS_LANG
   ORA_NLS33
   ORACLE_TERM
   LD_LIBRARY_PATH
  
   (technically, only $ORACLE_HOME is required, but you'll want to set the rest in order to make sure things run smoothly afterward)
  
5.  Make sure '/usr/ccs/bin' is in your path.  If not, add it.
6.  Unpack PHP source (php-4.2.3):

   gunzip php-4.2.3.tar.gz
   tar xvf php-4.2.3.tar
   cd php-4.2.3

  
7.  Run PHP configure like so :

   CC=gcc ./configure --with-apxs=/usr/local/apache/bin/apxs \
   --with-config-file-path=/etc \
   --with-mysql \
   --enable-ftp \
   --with-oci8=/path/to/ORACLE_HOME \
   --with-oracle=/path/to/ORACLE_HOME \
   --enable-sigchild
  
8.  Run make:  make
9.  Run this as root:  make install
10.  Change the LoadModule line in httpd.conf to include the fully qualified path.  For us:

   LoadModule php4_module        /usr/local/apache/libexec/libphp4.so
  
11.  Make sure the PHP files types are recognized in your httpd.conf file:

   AddType application/x-httpd-php .php
   AddType application/x-httpd-php-source .phps
  
12.  Test the configuration:

   /usr/local/apache/bin/apachectl configtest
  
   It should return "Syntax OK"
  
13.  Bounce Apache:

   /usr/local/apache/bin/apachectl restart
  
  
14.  Here's a simple PHP script to test the setup.  If you don't have access to the default tables Oracle provides, change the connections/tablenames/fields to match your setup:

   <?php

   $db_conn
= ocilogon("scott", "tiger");

  
$cmdstr = "select ename, sal from emp";
  
$parsed = ociparse($db_conn, $cmdstr);
  
ociexecute($parsed);
  
$nrows = ocifetchstatement($parsed, $results);
   echo
"Found: $nrows results<br><br>\n";

   echo
"<table border=1 cellspacing='0' width='50%'>\n";
   echo
"<tr>\n";
   echo
"<td><b>Name</b></td>\n";
   echo
"<td><b>Salary</b></td>\n";
   echo
"</tr>\n";

   for (
$i = 0; $i < $nrows; $i++ ) {
         echo
"<tr>\n";
         echo
"<td>" . $results["ENAME"][$i] . "</td>";
         echo
"<td>$ " . number_format($results["SAL"][$i], 2). "</td>";
         echo
"</tr>\n";
   }

   echo
"</table>\n";

  
?>
poulman at uponorhsdna dot com
10-Oct-2002 06:51
Re: ora-12154 errors with PHP 4.2.3, Apache 1.3.27, and Oracle 9i (client only) I had two identical set ups, one on SuSE 8.0 and one on RedHat 8.0, the SuSE worked and RedHat errored with ora-12154! For some reason, having the apache user in the oracle group worked for SuSE but did not for RedHat, I had to run the Apache service as oracle user (