PHP中 ADOdb 類庫介紹(轉)

BSDLite發表於2007-08-15
PHP中 ADOdb 類庫介紹(轉)[@more@]前言 為什麼要使用資料庫類庫? 初學者 (甚至一些非初學者)常常犯的錯誤,就是在開發應用程式的時候,缺乏對未來的考慮。假如有一天,你的程式需要使用其它的資料庫,難道你還需要重新寫一篇針對於這個版本資料庫的程式嗎?這不是不可能發生的,尤其是當目前的資料庫可能不適合你當前的需要的時候。 但是當你做這一切的時候 ,你會發現絕非你想像的那樣容易:每一個 DBMS 有不同的函式。舉例來說:在 Mysql 中連線資料庫的函式為 mysql_connect(),而在MSSQL卻是 mssql_connect()。重新檢視你所有的程式碼,然後修改所有運算元據庫的函式和查詢語法,這絕不是一項簡單的工作。程式會經常的被捆綁到了錯誤的資料庫上,以至無法在執行時達到最優效能。資料庫類庫就是這樣產生的。它允許你透過同樣的程式碼來操作不同的資料庫。一個設計良好的資料庫類庫可以完美的改變這一切。它允許你透過極小的修改,就能轉接到其他資料庫:無論你要連線什麼資料庫管理系統,只要使用同一個的函式,和不同的引數。舉例來說, 在 ADOdb 中,只需簡單地將 $db = NewADOConnection('access ') 修改為$db = NewADOConnection('mysql'),這樣,你就輕鬆的把你的程式從 Access 資料庫轉移到了 Mysql 資料庫中。現在網路上已經有了很多這樣的資料庫類庫,比如Pear,PHPlib,我也已經在工作中使用它們了,也許你也曾經用過。但本文僅將重點放在我所特別關注的 ADOdb。本文我只簡要地作一個介紹,使你能夠馬上運用它來開發你的下一個專案。以後的文章中我們將會循序漸進的對它進入更深入的瞭解。 目前,ADOdb 支援的資料庫包括 MySQL, PostgreSQL,Interbase,Firebird,Informix,Oracle,MS SQL 7,Foxpro,Access,ADO,Sybase,FrontBase,DB2 和 generic ODBC。 ADOdb 的安裝 安裝 ADOdb 是一件極期容易的事,相信聰明的你一定不會感到吃力。 首先, 確定你正在執行的 PHP 是 4.0.4 版或更新版。 如果不是,我強列建議你升級! 從 PHP Everywhere 站點下載 .zip 或 .tgz 檔案,解壓縮到你所選的路徑下。 這個路徑不應在網頁目錄(WWWTREE,譯者注:如果你的網頁是在/www/下,那麼,這個目錄就不應為/www/here)下!雖然ADOdb的包含檔案已經使用了 .inc.php 的副檔名 ,使得伺服器即使是在最糟糕的配置下,也不會將這些.inc檔案透過明文方式在瀏覽器中顯示出來,但是我們向來不提倡將庫函式檔案放在網頁目錄下的行為。然後把下載下來的檔案執行:tar -zxvf adodb350.tgz 解壓,在Windows下你可以使用一個你喜歡的解壓軟體來操作,這樣,你會得到一個 adodb 的目錄其下包括了許多子目錄。 測試你的安裝 好了,讓我們來測試一下你的安裝吧。 透過在指令碼中新增下列三行程式碼來測試你的安裝是否成功。注意要把程式碼中的引數修改成你自己的。 include("$adodb_path/adodb.inc.php"); // includes the adodb library $db = NewADOConnection('$database_type'); // A new connection $db->Connect("$host", "$user", "$password", "$database_name"); 現在你已經擁有一個資料庫連線物件 $db 了。 你也可以使用 ADONewConnection 來替換 NewADOConnection —— 這兩個是同一函式的不同的名字。 連線的資料庫變數 $database_type 需要針對你的實際情況改成你所需要的。可以使用以下列表中的一個(括號內的為描述部分,不要在程式碼中使用): access (Microsoft Access/Jet) ado (Generic ADO, the base for all the other ADO drivers) ado_access (Microsoft Access/Jet using ADO) ado_mssql (Microsoft SQL Server using ADO) db2 (DB2) vfp (Microsoft Visual FoxPro) fbsql (FrontBase) ibase (Interbase 6 or before) firebird (Firebird) informix72 (Informix databases before Informix 7.3) informix (Informix) maxsql (MySQL with transaction support) mssql (Microsoft SQL Server 7) mssqlpo (Portable mssql driver) mysql (MySQL without transaction support) mysqlt (MySQL with transaction support, identical to maxmysql) oci8 (Oracle 8/9) oci805 (Oracle 8.0.5) oci8po (Oracle 8/9 portable driver) odbc (Generic ODBC, the base for all the other ODBC drivers) odbc_mssql (MSSQL via ODBC) odbc_oracle (Oracle via ODBC) oracle (Oracle 7) postgres (PostgreSQL) postgres64 (PostgreSQL 6.4) postgres7 (PostgreSQL 7, currently identical to postgres ) sqlanywhere (Sybase SQL Anywhere) sybase (Sybase) 如果你的連結程式碼出現了錯誤的提示,那麼你首先要檢查的地方就是在路徑或連線的變數上。在你責備 ADOdb 之前,請確定你是已經正確的使用那些變數。(很多朋友常花太多時間去修正這些顯而易見的錯誤。) 如果連線沒有任何錯誤提示,那麼我們現在已經可以在我們的專案中來使用 ADodb 了。 透過你的指令碼連線到資料庫 把上邊的程式碼加入到你的程式碼前,讓我們先退一步。我們最好能把上邊的程式碼用我們自己的方法來封裝起來。這樣可以使你的程式變得更靈活、更具移植性。如果你直接把上面的程式碼插入到你的專案的每個檔案中,如果將來專案的路徑改變了,將會很容易產生錯誤,如果你的密碼改變了,你可能需要對你所有的指令碼進行修改,這樣將會影響我們使用庫函式的初衷。並且,因為你的密碼資訊是在WEBTREE下的,這將產生隱患。我推薦將密碼資訊放在一個獨立的包含檔案中,比如在 ADOdb 安裝目錄下的某個地方。如果你要在其他伺服器上執行你的程式時,你就不能保證目錄結構會是相同的,所以,你要確保這個路徑是正確的。我建議使用PHP 的自動包含功能來自動地包含這個檔案。 include("$adodb_path/db_values.inc.php"); include("$adodb_path/adodb.inc.php"); $db = NewADOConnection('$database_type'); $db->Connect("$host", "$user", "$password", "employees"); 如果你也想要使用持久連線, 不是每次創造一個新的連線(這使許多WEB應用程式得到了加速,但是要注意有些資料庫是不支援的)。可以使用 PConnect 替換掉 Connect。 檔案 db_values.inc.php 是我們的資料庫資訊檔案,內容為(你需要把下面程式碼中的變數改成你自己的): 你可以在 php.ini 配置中設定自動包含我們的配置檔案,具體操作可以修改 PHP.ini 的下述行: ; Automatically add files before or after any PHP document. auto_prepend_file = /usr/local/build/apache/www/tool_lib/defaults.inc auto_append_file = 檔案 defaults.inc 包含了 $adbdb_path 的值: 還有其他方式來實現它,但是我發現這種方法在移植時,可以相對地減少複雜度。 從一個資料庫中進行選擇(SELECT)操作 當同時使用開發良好的庫函式,和PHP自身提供的函式時,可以有多種方法來訪問資料庫。用什麼方法,完全取決於你自己的喜好。 這裡是一個簡單的例子: $sql = "SELECT surname, age FROM employees"; $rs = &$db->Execute($sql); if (!$rs) { print $db->ErrorMsg(); // Displays the error message if no results could be returned } else { while (!$rs->EOF) { print $rs->fields[0].' '.$rs->fields[1].'
'; // fields[0] is surname, fields[1] is age $rs->MoveNext(); // Moves to the next row } } 在上例中,$rs->fields 是一個包含返回值的陣列。陣列索引被賦予了初始的數字,你也可以按下面的方法來指定其索引: $sql = "SELECT surname, age FROM employees"; $db->SetFetchMode(ADODB_FETCH_ASSOC); // Return associative array $rs = &$db->Execute($sql); if (!$rs) { print $db->ErrorMsg(); // Displays the error message if no results could be returned } else { while (!$rs->EOF) { print $rs->fields['surname']." ".$rs->fields['age']."
"; $rs->MoveNext(); // Moves to the next row } // end while } // end else 對結果瀏覽的另一個可選的方法是將每條記錄作為一個物件返回。 ADOdb 有一個 FetchNextObject() 的函式來實現這一功能,指標會自動地移到下一條記錄。 $sql = "SELECT surname, age FROM employees"; $db->SetFetchMode(ADODB_FETCH_ASSOC); // Return associative array $rs = &$db->Execute($sql); if (!$rs) { print $db->ErrorMsg(); // Displays the error message if no results could be returned } // loop through results while ($row = $rs->FetchNextObject()) { // The field names need to be uppercase print $row->SURNAME." ".$row->AGE."
"; } 插入、更新記錄 基本的 INSERT 操作方便、快捷, 擁有與SELECT一樣的語法。 $sql = "INSERT INTO employees (surname, age) values ('Clegg','43')"; if (!($db->Execute($sql))) { print 'Error inserting: '.$db->ErrorMsg().'
'; } 庫函式真正的優點,在於它允許你透過相同的語法將記錄放入不同的資料庫之內,這在以前是絕對不可能的。通常有兩種發生的情形。 第一種,引號。所有的引號需要用脫字元(即`符號,鍵位在Tab鍵的上邊)代替,否則會引起語法錯誤。但是一些資料庫使用一個單引號,另外一些則使用兩個單引號。所以,你應當使用 ADOdb 中的 qstr() 而不是 PHP 中的 addslashes()。這樣,返回值就將與你所使用的資料庫相吻合了。 第二種,日期。許多資料庫接受跟他們的日期型別不一致的、不相容的格式。 ADOdb 有一個 DBDate() 函式,可以將 Unix 的 timestamp, 或 ISO(Y-m-d) 格式轉換成任意格式,以此來滿足你的資料庫的需求。 見下例: $employee_surname = $db->qstr("d'Angelo"); $arrival_time = $db->DBDate(time()); // The above two functions also add the enclosing quotes, so, $arrival_time, not '$arrival_time' $sql = "INSERT INTO employee_arrival (arrival_time,surname) values ($arrival_time,$employee_surname)"; if (!($db->Execute($sql))) { print 'Error inserting: '.$db->ErrorMsg().'
'; } 你可以以完全相同的方式更新資料庫,舉例來說: $sql = "UPDATE employees SET age='44' WHERE id='121')"; if (!($db->Execute($sql))) { print 'Error updating: '.$db->ErrorMsg().'
'; } 以上僅僅是 Adodb 的一些基本操作 —— 下次我們將會關注一些 ADOdb 提供的比較深層次的東西。 如果我已經使你胃口大開,而且你已經不能再等待, 我建議你去PHP Everywhere看一下,這個站點是ADOdb的專業站點,裡面有很多有用的幫助資訊。 對查詢進行快取 上個月,我們簡單地瞭解了ADOdb中,如何進行SELECT、INSERT和UPDATE的操作。如果你在ADOdb上是個新手,我建議先讀一下上個月的那篇文章。 ADOdb 還有很多更高階的特徵,這個月,我們就一起來關注其中的部分內容。 資料庫時常會成為應用程式效率低下的禍首。儘量減少對資料庫的查詢,是提高執行效率的方法之一。這,通常可以透過對整頁內容進行快取(有很多種方法來實現。比如,PEAR->Cache),或者,如果你需要做一張動態頁面,並且只想讓查詢指令被快取,那麼,你可以使用ADOdb,簡單地將查詢指令快取起來。在你檢視透過快取來提高你的應用程式的糟糕效能之前,我建議你先試圖去最佳化你的查詢指令。有時候,一些簡單的索引可以改變一切——有太多的所謂的專業的解決方案,都在使用糟糕的索引。在本文中,你能找到很多這樣的例項。現在,讓我們來看看ADOdb是如何使你能夠對資料庫的查詢結果進行快取的。在這個例項中,ADOdb把我們的最後的一次查詢的結果儲存在/var/tmp/adodb_cache這個快取檔案中,並保留10分鐘。 include("$adodb_path/db_values.inc.php"); include("$adodb_path/adodb.inc.php"); $db = NewADOConnection('$database_type'); $db->Connect("$host", "$user", "$password", "employees"); $ADODB_CACHE_DIR = "/var/tmp/adodb_cache"; //Directory to store cached files $sql = "SELECT surname, age FROM employees"; $rs = &$db->CacheExecute(600,$sql); // Executes, and caches the results for 600 seconds if (!$rs) { print $db->ErrorMsg(); // Displays the error message if no results could be returned } else { while (!$rs->EOF) { print $rs->fields[0].' '.$rs->fields[1].'
'; // fields[0] is surname, fields[1] is age $rs->MoveNext(); // Moves to the next row } // end while } // end else CacheExecute() 函式有兩個引數: 第一個引數是快取檔案將被保留的時間,以秒計時;第二個引數是 SQL 宣告。 第一個引數是可選擇的 (一些開發者或許會認為它應當成為第二個引數) ,如果你沒有限定時間,那麼,預設值是 3600 秒,也就是1個小時。快取檔案被命名為 adodb_*.cache,你可以在檔案系統中安全地將他們刪除。你應該定期清楚過期的快取檔案(用UNIX的“crontab萬年曆”,或者WINDOWS的“計劃任務”。譯者注:萬年曆不知有沒有譯錯,我沒有UNIX。)。要注意的是,要使用快取方法,你需要將PHP的引數magic_quotes_runtime設為off(譯者注:在php.ini中,將值設為0)。你可以根據需要,在執行時修改它的值: set_magic_quotes_runtime(0); 只需將上述程式碼放到你呼叫資料庫的指令之前就可以了。你可以在任何時候,透過呼叫CacheFlush();來清除快取。處於對安全的考慮,ADOdb 也建議將PHP的引數register_globals 設為0(在PHP最新版中,這是預設值) 。 更多關於查詢結果的資訊 開發者通常會對他們的要得到的結果產生一些質疑,最通常的問題是:有多少個記錄?ADOdb能夠很容易地透過RecordCount()來回答這個問題。 RowCount()是同義函式。 $sql = "SELECT surname, age FROM employees"; $rs = &$db->CacheExecute(600,$sql); // Executes, and caches the results for 600 seconds print $rs->RecordCount() . " rows returned]"; // Display number of rows returned 或許第二個問題會產生在需量列表上:被返回欄位數量是多少?不用擔心,ADOdb有FieldCount()。 $sql = "SELECT surname, age FROM employees"; $rs = &$db->CacheExecute(600,$sql); // Executes, and caches the results for 600 seconds print $rs->FieldCount() . " columns returned]"; // Display number of rows returned 限制結果 上次我們討論瞭如何透過使用一個資料庫庫函式使你的應用程式更簡潔,更易於移植。在從MySQL轉移到 Informix中 , 我經歷了一次痛苦的移植過程。一切都歸咎於非ANSII標準的LIMIT子句( 舉例來說, 在MySQL中允許下列指令:SELECT name FROM employee LIMIT 15),它是一個非常有用的功能,可在Informix中卻不被支援。(在Informix中,相同功能的書寫應該是:SELECT FIRST 15 name FROM employee in Informix。)它似乎對你敲響了警鐘,要你停止在你的查詢中使用非標準SQL的指令,而去認真地學習標準的SQL。幸運的是,ADOdb有一個處理LIMIT的方法:SelectLimit()。 $sql = "SELECT surname, age FROM employees"; $rs = &$db->SelectLimit($sql, 10, 100); // Select 10 rows, starting at row 100 if (!$rs) { print $db->ErrorMsg(); // Displays the error message if no results could be returned } else { while (!$rs->EOF) { print $rs->fields[0].' '.$rs->fields[1].'
'; // fields[0] is surname, fields[1] is age $rs->MoveNext(); // Moves to the next row } // end while } // end else SelectLimit()將SQL宣告作為第一引數,第二個是返回的列的數量,最後一個引數是偏移量(返回的第一行)。注意這跟MySQL的指令中LIMIT子句的引數順序相反。SelectLimit()對於將搜尋結果部分地顯示在頁面上,是十分有用的,透過Previous和Next按鈕,可以瀏覽所有的結果。 不止一次地,我看到的程式碼將來自資料庫的所有查詢結果,都用PHP作過濾處理——殺雞用牛刀! 你完全可以使用 CacheSelectLimit()函式來貯藏這種型別的結果。 處理事務 處理事務是許多應用程式的一個重要的特徵。(對於初學者來說,處理事務是你可以提交一打查詢操作的過程,而這些查詢是都成功了,還是有部分失敗了,都需要考慮進去。 經典範例是銀行處理。錢從你的帳戶轉出,然後轉入到其他某個人的帳戶中。只要其中任意一項失敗,那麼,這整個過程都必須被認定為失敗。不然,錢被劃出,而沒有進對方的帳戶;或者,錢沒有劃出,對方帳戶無端多了一筆小費。) 處理事務可以在程式碼級上進行機警地管理控制。 常數錯誤檢查被用來判斷是否要COMMIT(事務的所有各項都正確,執行正確,結束事務)還是ROLLBACK(事務中有錯誤,所有改動需要恢復原來狀況)。ADOdb 有一些能使處理操作正確進行的有用的函式。下例在某個職員的結餘加10,並在另一個上減10,整個過程有兩個查詢,作為一個完整的事務。 $sql1 = "UPDATE employees SET balance=balance-10 WHERE id=15"; $sql2 = "UPDATE employees SET balance=balance+10 WHERE id=22"; $db->StartTrans(); $db->Execute($sql); $db->Execute($sql2); $db->CompleteTrans(); 當你瀏覽老的程式碼時,可能會看到一個比較老的方法來實現這一切。使用 BeginTrans()、CommitTrans()和RollbackTrans()函式時,需要你自己來處理錯誤。StartTrans()和 CompleteTrans()將會自動地處理錯誤,並適當地進行COMMIT或ROLLBACK。當需要的時候,你可以透過FailTrans()來強制執行ROLLBACK。 當然你可能需要知道處理是失敗了還是成功了。ADOdb 提供了 HasFailedTrans() 來實現這個功能。 如果出錯(或者,你可以將這種情況稱作FailTrans()),返回TRUE;如果成功,返回FALSE。 $sql1 = "UPDATE employees SET balance=balance-10 WHERE id=15"; $sql2 = "UPDATE employees SET balance=balance+10 WHERE id=22"; $db->StartTrans(); $db->Execute($sql); $db->Execute($sql2); $db->CompleteTrans(); if ($db->HasFailedTrans()) { // Something went wrong } 值得注意的是,你的資料庫需要支援這些事務函式。 (大多數的資料庫是支援的,不過,MySQL InnoDB表支援,可 MySQL MyISAM 表不支援。) 我希望我所做的一切能讓你對資料庫庫函式能有極大的興趣。還有大量有趣的函式可以用來從資料庫表中自動生成HTML,並且同一結果有不同的方法來實現。你可以在此找到完整的手冊。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-959849/,如需轉載,請註明出處,否則將追究法律責任。

相關文章