模仿前人的程式,寫了一段超迷你的程式要連 Oracle,但一直跳出的錯誤訊息:

PHP Fatal error:  Call to undefined function Ora_Logon()

查了一下官方文件,Ora_* 這種函式看起來不是官方支援的,網路上的文章倒是不少,可能是過時所以被拿掉了吧?向同事拿了他開發機上頭 PHP 的 ext 資料夾底下的 php_oracle.dll,嘗試在 php.ini 加上 "extension=php_oracle.dll",結果出現新的錯誤:

PHP Startup: Unable to load dynamic library 'C:/php/ext/php_oracle.dll' - 找不到指定的模組。

怪了,明明就放在一樣的路徑下。研究別人找不到模組的原因,有人說和引用順序有關,於是放在 ";extension=php_oci8.dll" 這行之後,一樣沒用,不過把 ";extension=php_oci8.dll" 的註解拿掉(這行最前面的分號刪除掉),「找不到指定的模組」這個錯誤訊息就消失了。但還是不認得 Ora_Logon() 這個函式。

 

《[筆記]oracle+php+apache在windows下的的安裝方式》這篇提醒了我,php_oci8.dll 需要安裝 Oracle Client library 才能使用(其實 PHP 官方文件也有說啦 XD),因此我按照網路上的建議下載了 Oracle Instant ClientPHP 官方文件說要記得在 PATH 裡設定 Oracle Instant Client 的路徑。

一開始我因為 Windows 是 64 位元版本,下載了 64 bits 版本的 Oracle Instant Client (instantclient-basic-win-x86-64-10.2.0.3.0.zip),一直跳出錯誤訊息:

PHP Warning:  PHP Startup: Unable to load dynamic library 'C:/php/ext/php_oci8.dll' - %1 不是正確的 Win32 應用程式 。

後來看了 Oracle 官網上的教學文章:《 在 Linux 和 Windows 上安裝 PHP 和 Oracle Instant Client》,裡說到一句話:「因為 PHP 是 32 位,所以使用 32 位版本的 Instant Client。

所以把 Oracle Instant Client 換成 32 bits 版本 (instantclient-basic-win32-10.2.0.3-20061115.zip) 就沒事了。

這時候 oci8 模組已經啟用了,可是舊版的 oracle 模組還是載不進來,又再次看見這個錯誤訊息:

PHP Warning:  PHP Startup: Unable to load dynamic library 'C:/php/ext/php_oracle.dll' - 找不到指定的模組。

對此現象深感無奈,加上 ora_* 的函式都已經過時了,於是這篇文章的標題就從「使用 Oracle 相關函式 (ora_*) 的前置設定」變成「如何使用 PHP 的 OCI8 連線至 Oracle」了。XD

 

OCI8 模組可以用了以後,我連線一直失敗。我設定的 connection string 是這樣(IP 和 SID 是假的,請依實際狀況填寫):

$oracle_db = "
(DESCRIPTION=
    (ADDRESS_LIST =
        (ADDRESS =
            (PROTOCOL = TCP)
            (HOST = 10.1.1.1)
            (PORT = 1521)
        )
    )
    (CONNECT_DATA=
        (SID = testdb)
    )
)";

得到的錯誤訊息是這個:

ORA-12154: TNS:could not resolve the connect identifier specified

但萬分悲情的是,我試著把 connection string 改成這樣:

$oracle_db = "//10.1.1.1/testdb"

赫然發現真正的錯誤訊息是我的帳號密碼根本 key 錯:

ORA-01017: invalid username/password; logon denied

打錯密碼就打錯密碼,有必要跟我說我的連線無法識別嗎?(淚)

 

所以最後記錄一下我連線取資料所使用的程式碼片段:

<?php
$oracle_db="
(DESCRIPTION=
    (ADDRESS_LIST =
        (ADDRESS =
            (PROTOCOL = TCP)
            (HOST = 10.1.1.1)
            (PORT = 1521)
        )
    )
    (CONNECT_DATA=
        (SID = testdb)
    )
)";

$sql="select city_name, city_id from city";

$conn=oci_connect($db_user_id,$db_user_pwd,$oracle_db);
if(!$conn){
    echo"db access error: ".oci_error();
}
else{
    try{
        $stid=oci_parse($conn,$sql);

        oci_define_by_name($stid,'CITY_ID',$city_id);
        oci_define_by_name($stid,'CITY_NAME',$city_name);

        oci_execute($stid);

        while(($row=oci_fetch_array($stid,OCI_ASSOC+OCI_RETURN_NULLS))){
            echo"city_id: ".$bond_id.", city_name: ".$city_name;
        }
    }
    catch(Exception $e){
        echo$e->getMessage();
    }

    if($stid){oci_free_statement($stid);}
    if($conn){oci_close($conn);}
}
?>
arrow
arrow
    文章標籤
    php apache oracle
    全站熱搜

    小攻城師 發表在 痞客邦 留言(2) 人氣()