Oracle Instant Client 僅需 ~80MB 庫檔即可提供完整 OCI8 連線能力,無需完整 Client 安裝。本文詳述 Windows/Linux 環境下 PHP 7/8 啟用 OCI8 擴充、Instant Client 部署、環境變數配置、連線字串最佳實踐與故障排查。
oci.dll, oraocieiXX.dll, orannzsbbXX.dll)。oci.h, oratypes.h 等標頭,編譯 PHP OCI8 擴充需用)。# 建議目錄
C:\instantclient_21_10\
oci.dll
oraociei21.dll
orannzsbb21.dll
# 若使用舊版 PHP oracle 擴充 (php_oci8.dll) 需 ociw32.dll 而非 oci.dll
C:\instantclient_21_10,**置於最頂端** (優先於其他 Oracle Home)。C:\instantclient_21_10,將 tnsnames.ora, sqlnet.ora 放在此目錄。AMERICAN_AMERICA.AL32UTF8 (或 TRADITIONAL CHINESE_TAIWAN.ZHT16MSWIN950),避免中文亂碼。ORACLE_HOME, ORACLE_SID (Instant Client 不使用)。; php.ini
extension=oci8
; PHP 7/8: extension_dir = "C:\php\ext"
; PHP 5: extension_dir = "C:\php\extensions"
重啟 Apache / PHP-FPM / IIS (FastCGI)。
<?php phpinfo(); ?>
瀏覽器開啟,搜尋 oci8 區塊 → 應顯示 OCI8 Support => enabled、Oracle Run-time Client Library Version => 21.x。
# Oracle Linux / RHEL / CentOS (yum/dnf)
dnf install -y oracle-instantclient21.10-basic oracle-instantclient21.10-devel
# Ubuntu / Debian (轉換 RPM 或使用 Alien)
alien -i oracle-instantclient21.10-basic-*.rpm
alien -i oracle-instantclient21.10-devel-*.rpm
# 安裝路徑通常為:
# /usr/lib/oracle/21.10/client64/lib/ (庫檔)
# /usr/include/oracle/21.10/client64/ (標頭)
mkdir -p /opt/oracle/instantclient_21_10
cd /opt/oracle/instantclient_21_10
unzip instantclient-basic-linux.x64-21.10.0.0.0dbru.zip
unzip instantclient-sdk-linux.x64-21.10.0.0.0dbru.zip
# 建立軟連結 (某些舊版 PHP 需要)
ln -s libclntsh.so.21.1 libclntsh.so
ln -s libocci.so.21.1 libocci.so
# 安裝建構依賴
dnf install -y php-devel php-pear gcc make libaio # 或 apt install php-dev ...
# 下載 PHP 原始碼 (對應版本)
wget https://www.php.net/distributions/php-8.2.10.tar.gz
tar xzf php-8.2.10.tar.gz
cd php-8.2.10/ext/oci8
# phpize 配置
phpize
./configure --with-oci8=instantclient,/usr/lib/oracle/21.10/client64/lib
# 或手動指定 SDK 路徑
# ./configure --with-oci8=instantclient,/opt/oracle/instantclient_21_10
make && make install
# 啟用擴充
echo "extension=oci8.so" > /etc/php.d/20-oci8.ini
# /etc/sysconfig/httpd 或 systemd drop-in
export LD_LIBRARY_PATH=/usr/lib/oracle/21.10/client64/lib:$LD_LIBRARY_PATH
export TNS_ADMIN=/etc/oracle # 放置 tnsnames.ora
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
systemd 服務:
# /etc/systemd/system/httpd.service.d/oracle.conf
[Service]
Environment=LD_LIBRARY_PATH=/usr/lib/oracle/21.10/client64/lib
Environment=TNS_ADMIN=/etc/oracle
Environment=NLS_LANG=AMERICAN_AMERICA.AL32UTF8
systemctl daemon-reload
systemctl restart httpd php-fpm
# 或 apachectl restart
| 模式 | 範例 | 適用場景 |
|---|---|---|
| Easy Connect (無 tnsnames.ora) | $c = oci_connect('hr', 'pass', '//dbhost:1521/ORCLPDB'); | 簡單部署、容器化、無集中管理需求 |
| TNS Alias (tnsnames.ora) | $c = oci_connect('hr', 'pass', 'ORCLPDB'); (需 TNS_ADMIN) | 生產環境、多資料庫、負載平衡、FAILOVER |
| 環境變數預設 | $c = oci_connect('hr', 'pass'); (需 TWO_TASK/LOCAL=ORCLPDB) | 腳本簡化、Cron 任務 |
<?php
$conn = oci_connect('hr', 'hr_password', '//dbhost:1521/ORCLPDB');
if (!$conn) { $e = oci_error(); die(htmlentities($e['message'])); }
$stid = oci_parse($conn, 'SELECT table_name FROM user_tables ORDER BY table_name');
oci_execute($stid);
echo "<table border=1><tr><th>TABLE_NAME</th></tr>";
while ($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
echo "<tr><td>".htmlentities($row['TABLE_NAME'])."</td></tr>";
}
echo "</table>";
oci_free_statement($stid);
oci_close($conn);
?>
| 現象 | 檢查項目 | 解決 |
|---|---|---|
| phpinfo() 無 oci8 區塊 | php.ini extension=oci8 未生效 / extension_dir 錯誤 | php -m | grep oci8;修正 php.ini 路徑與擴充檔名 (php_oci8.dll / oci8.so) |
| Apache 啟動錯誤: OCI.dll not found | PATH 未包含 Instant Client 目錄 / 順序錯誤 | 系統 PATH 最前端加入 Instant Client 目錄;重啟 Apache 服務 (非僅 reload) |
| ORA-12154: TNS:could not resolve | tnsnames.ora 路徑/語法錯誤 / TNS_ADMIN 未設定 | 確認 TNS_ADMIN 指向含 tnsnames.ora 目錄;用 tnsping 測試 |
| ORA-12541: TNS:no listener | 監聽器未啟動 / 埠號/防火牆 | lsnrctl status; firewall-cmd --add-port=1521/tcp |
| ORA-28040: No matching authentication protocol | 資料庫 12c+ 僅支援 SHA-2/512,舊版 Instant Client 不相容 | 升級 Instant Client 至 12.2+ / 19c / 21c |
| 中文亂碼 | NLS_LANG 未設定或與資料庫字元集不符 | 設定 NLS_LANG=AMERICAN_AMERICA.AL32UTF8 (資料庫為 AL32UTF8 時) |