本文介紹基於PHP與Oracle 7.x構建的留言簿系統,包含數據表設計、環境變量配置、OCI8擴展編譯、新增留言核心代碼,展示早期企業級PHP應用與商業數據庫集成模式。
CREATE TABLE guestbook (
serial VARCHAR2(255) NOT NULL, -- 流水號(主鍵)
ref VARCHAR2(255), -- 參照流水號(回覆功能預留)
id CHAR(8) NOT NULL, -- 用戶帳號
alias VARCHAR2(32) NOT NULL, -- 顯示名稱
ip VARCHAR2(1024), -- 客戶端IP
msgdate DATE NOT NULL, -- 留言時間
email VARCHAR2(1024), -- 電子郵箱
msg VARCHAR2(2000) NOT NULL, -- 留言內容
flag CHAR(1) DEFAULT '1', -- 顯示標誌:0隱藏 1顯示
PRIMARY KEY (serial)
);
<?php
// 必須設置的Oracle環境變量
putenv("ORACLE_SID=WWW");
putenv("NLS_LANG=AMERICAN_TAIWAN.ZHT16BIG5"); // 字符集:繁體中文Big5
putenv("ORACLE_HOME=/home/oracle/product/7.3.2");
putenv("LD_LIBRARY_PATH=/home/oracle/product/7.3.2/lib");
putenv("ORA_NLS=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
putenv("ORA_NLS32=/home/oracle/product/7.3.2/ocommon/nls/admin/data");
// 編譯PHP時需指定:--with-oci8=/home/oracle/product/7.3.2
?>
環境變量缺失會導致ora_logon失敗,錯誤極難排查。現代Oracle Instant Client部署更簡單(LD_LIBRARY_PATH指向instantclient目錄即可)。
<?php
if (($alias != "") && ($msg != "")) {
// 1. 連接數據庫
$conn = ora_logon("user38@WWW", "iam3849") or die("連接失敗");
$cursor = ora_open($conn);
ora_commitoff($conn); // 關閉自動提交,手動控制事務
// 2. 構建數據
$serial = md5(uniqid(rand())); // 唯一流水號
$ref = "";
$id = $PHP_AUTH_USER; // HTTP基本認證用戶名
$ip = $REMOTE_ADDR;
$msg = base64_encode($msg); // 內容Base64編碼存儲
$flag = "1";
// 3. 執行插入(使用Oracle SYSDATE)
$sql = "INSERT INTO guestbook (serial, ref, id, alias, ip, msgdate, email, msg, flag)
VALUES ('$serial', '$ref', '$id', '$alias', '$ip', SYSDATE, '$email', '$msg', '$flag')";
ora_parse($cursor, $sql) or die("SQL解析失敗");
ora_exec($cursor);
ora_commit($conn); // 手動提交
// 4. 清理資源
ora_close($cursor);
ora_logoff($conn);
echo "留言發布成功!";
}
?>
| 特性 | OCI8早期寫法 | 現代PDO/OCI8最佳實踐 |
|---|---|---|
| 連接 | ora_logon() | new PDO('oci:dbname=WWW', $user, $pass) |
| 預處理 | 不支持,字符串拼接 | $stmt->execute([...])防注入 |
| 事務 | ora_commitoff/commit | PDO::beginTransaction/commit/rollback |
| 錯誤處理 | or die()中斷執行 | PDO::ERRMODE_EXCEPTION拋出異常 |
| 字符集 | NLS_LANG環境變量 | DSN指定charset=AL32UTF8 |
| 結果集 | ora_fetch_into | $stmt->fetch(PDO::FETCH_ASSOC) |
Oracle 7無LIMIT,需使用ROWNUM子查詢:
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM guestbook WHERE flag='1' ORDER BY msgdate DESC
) a WHERE ROWNUM <= :end_row
) WHERE rn >= :start_row
Oracle 12c+支持標準OFFSET ... ROWS FETCH NEXT ... ROWS ONLY語法。
VARCHAR2(1024)無問題,但建議標準VARCHAR2(45)此系統展示了PHP早期與商業數據庫深度集成的典型模式,雖API風格已過時,但「環境變量配置、手動事務控制、字符集聲明」等核心概念在現代OCI8/PDO開發中依然適用。