PDO_OCI 和 OCI8 是两个平行、独立的 Oracle 数据库驱动,都直接基于 Oracle Instant Client 的 OCI C API 实现,互不依赖,可以单独或同时使用。
如果你当前项目是基于 PDO 的现代应用,优先考虑 PDO_OCI(安装方式比 OCI8 简单一些);如果需要更强大的 Oracle 原生功能,再装 OCI8。
在 Ubuntu 24.04(Noble Numbat)上,PHP 8.3 的 PDO_OCI 扩展 没有预编译的 apt 包(php8.3-pdo-oci 或类似不存在),官方 Ubuntu 仓库和 Ondřej Surý PPA 都不提供它。
PDO_OCI 扩展需要从 PHP 源码中编译(或通过 pecl install pdo_oci,但 pecl 版本在 PHP 8.3+ 上已过时或不推荐),并且必须依赖 Oracle Instant Client(与 OCI8 相同)。
下面是在 Ubuntu 24.04 + PHP 8.3 上开启 PDO_OCI 的推荐、可行步骤。
先决条件(必须先完成)
安装 Oracle Instant Client,具体如何安装参见Ubuntu24系统PHP8.3安装oci8扩展(针对Oracle Database 23ai Free数据库)的方法。
开启 PDO_OCI 的两种主要方式
方式一:、通过 pecl install pdo_oci(推荐先尝试,PHP 8.3+ 支持)
sudo pecl install pdo_oci
安装过程中会提示:
Please provide the prefix of Oracle installation:
输入你的 Instant Client 路径,例如:
instantclient,/opt/oracle/instantclient_23_26
如果成功,pecl 会自动安装并提示添加 extension=pdo_oci.so 到 php.ini。
启用扩展:
echo "extension=pdo_oci.so" | sudo tee /etc/php/8.3/mods-available/pdo_oci.ini
sudo phpenmod pdo_oci
重启服务(CLI 不需重启,但建议):
sudo systemctl restart php8.3-fpm # 如果用 FPM
sudo systemctl restart apache2
验证pdo_oci扩展是否成功启用:
php -m | grep -i oci
在输出中应该看到 pdo_oci。
方式二、从 PHP 源码手动编译(如果 pecl 失败,成功率更高)
1 下载 PHP 8.3 源码(要与你当前PHP版本匹配,例如 8.3.6):
wget https://www.php.net/distributions/php-8.3.6.tar.gz
tar -xzf php-8.3.6.tar.gz
cd php-8.3.6/ext/pdo_oci
2 准备编译:
phpize
3 配置(关键:指定 Instant Client 路径):
./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient_23_26
如果提示缺少头文件,确保 Instant Client 的 SDK 已解压(包含 include/ 目录)。
如果报错 oci.h not found:检查路径是否正确,或把 Instant Client 的 include 路径加到环境变量:
export CFLAGS="-I/opt/oracle/instantclient_23_4/sdk/include"
./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient_23_4
4 编译并安装:
make
sudo make install
5 启用扩展:
echo "extension=pdo_oci.so" | sudo tee /etc/php/8.3/mods-available/pdo_oci.ini
sudo phpenmod pdo_oci
sudo systemctl restart php8.3-fpm apache2
6 验证pdo_oci扩展是否成功启用:
php -m | grep -i oci
在输出中应该看到 pdo_oci。
编写测试脚本测试PDO_OCI扩展是否可用
创建测试脚本 test_pdo_oci.php:
<?php
try {
$dsn = 'oci:dbname=//127.0.0.1:1521/FREEPDB1;charset=AL32UTF8';
$pdo = new PDO($dsn, 'system', '你的密码');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->query('SELECT name, open_mode FROM v$pdbs');
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
echo "PDO_OCI 连接成功!\n";
} catch (PDOException $e) {
echo "连接失败: " . $e->getMessage();
}
运行:
php test_pdo_oci.php
如果输出 PDB 状态信息,说明成功。
常见问题和注意事项
- pecl install pdo_oci 报错:如果提示 “channel not found” 或版本过时,直接用方式 2 手动编译。
- libaio / libnnz / libclntsh 等库找不到:回到 Instant Client 环境变量设置 + ldconfig + 符号链接。
- PHP 版本不匹配:确保 phpize 来自 php8.3(phpize –version 应显示 8.3)。
- 生产环境:PDO_OCI 功能比 OCI8 弱(不支持某些高级绑定、LOB 流等),建议只用于简单 CRUD。如果项目允许,优先 OCI8。
最佳实践
- 企业级 / 复杂项目(涉及 PL/SQL、包、游标、大字段、分页优化):几乎 100% 用 OCI8。
- 简单读写(只是查询/插入几张表):PDO_OCI 也能用,但稳定性不如 OCI8。如果你的项目已经用了 PDO 统一抽象层,且只做简单操作,可以试 PDO_OCI。
- Oracle 官方和 PHP 社区也推荐 OCI8 作为 “premier interface” 用于 Oracle + PHP。