Pear DB 新手入門指南
(原文:《Quick Start Guide to Pear DB》)
翻譯:陳剛([email protected])
?
目???? 錄
1.??????? 簡介-------------------------------------------------------------------------------------2
2.??????? 下載、安裝Pear-------------------------------------------------------------------------2
3????????? 使用Pear DB----------------------------------------------------------------------------2
3.1.1?? 連接,斷開數據庫
3.1.2?? 執行數據庫
3.1.3?? 獲得select的數據
3.1.3.1? 獲取數據的函數
3.1.3.2? 選擇獲取數據的格式
3.1.3.3? 設置獲取數據的格式
3.1.3.4? 控制獲取數據數量
3.1.3.5? 清除結果,釋放變量
3.1.4?? 快速retrieve數據
3.1.5?? 從查詢結果獲得更多信息(numRows, numCols, affectedRows, tableInfo)
3.1.6?? 自動增長(Sequences)
3.1.7?? Prepare & Execute/ExcuteMultiple
3.1.8?? autoCommit, commit and rollback
4.??????? 可用方法列表---------------------------------------------------------------------------10
5????????? 錯誤處理機制---------------------------------------------------------------------------12
5.1???????? 從Pear DB Error獲得錯誤信息
5.2???????? Debug Pear DB Errors
5.3??????? 對錯誤採取自動處理
1.??????? 簡介
這是一部指導我們如何使用Pear DB擴展。Pear DB,提供這樣一系列的類:
n????????? 數據庫抽象
n????????? 高級錯誤處理機制
n????????? 以及其它
?
2.??????? 下載、安裝Pear
由於現在Pear項目仍處於緊鑼密鼓的開發之中,所以得到它的最好辦法就是從CVS獲得(Pear DB發行包已經跟隨PHP4.0.6以後版本捆綁發佈)。所以,我們只需要把Pear的根目錄放到php.ini配置文件include_path中。也可以通過這樣設置:_set('include_path', '/pear_base_dir').
以下是strp by step示例:
存放Pear的目錄: # cd /usr/local/lib 用“phpfi“口令登錄: # cvs -d :pserver:[email protected]:/repository login 用以下命令得到所有的pear文件,同時也可以用來更新已經下載的文件。其他的參數有:"today", "last month",等。我推薦用"last week"參數,因爲一般bugs的提交和修改都是每週一次。 # cvs -d :pserver:[email protected]:/repository export -D "last week" php4/pear 編輯php.ini文件加上下面一段在include_path處: /usr/local/lib/php4/pear 如果沒有修改的權限,可以通過這條語句在代碼中實現: ini_set('include_path', 'path_to_pear'); |
獲得PHP CVS的完全文檔
注意Pear DB必需PHP版本4.0.4以上,而在Pear中的一些其他包如:XML Parser of the pear installer script需要PHP4.0.5以上版本。
?
3.??????? 使用Pear DB
3.1???????? 連接,斷開數據庫
?
// The pear base directory must be in your include_path require_once? 'DB.php' ; $user? =? 'foo' ; $pass? =? 'bar' ; $host? =? 'localhost' ; $db_name? =? 'clients_db' ; // Data Source Name: This is the universal connection string $dsn? =? "mysql://$user:$pass@$host/$db_name" ; // DB::connect will return a Pear DB object on success // or a Pear DB Error object on error // You can also set to TRUE the second param // if you want a persistent connection: // $db = DB::connect($dsn, true); $db? =? DB :: connect ( $dsn ); // With DB::isError you can differentiate between an error or // a valid connection. if?( DB :: isError ( $db ))?{ ????????die?( $db -> getMessage ()); } .... // You can disconnect from the database with: $db -> disconnect (); ?>
?
|
數據源(上例中的$dsn 參數)有以下允許的格式:(從Pear/DB.php的parseDSN方法複製而來)
?
?????*??phptype: Database backend used in PHP (mysql, odbc etc.) ?????*??dbsyntax: Database used with regards to SQL syntax etc. ?????*??protocol: Communication protocol to use (tcp, unix etc.) ?????*??hostspec: Host specification (hostname[:port]) ?????*??database: Database to use on the DBMS server ?????*??username: User name for login ?????*??password: Password for login ?????* ?????* The format of the supplied DSN is in its fullest form: ?????* ?????*??phptype(dbsyntax)://username:password@protocol+hostspec/database ?????* ?????* Most variations are allowed: ?????* ?????*??phptype://username:password@protocol+hostspec:110//usr/db_file.db ?????*??phptype://username:password@hostspec/database_name ?????*??phptype://username:password@hostspec ?????*??phptype://username@hostspec ?????*??phptype://hostspec/database ?????*??phptype://hostspec ?????*??phptype(dbsyntax) ?????*??phptype
|
現在支持的數據庫有 (在 phptype DSN 部分):
?
mysql??-> MySQL pgsql??-> PostgreSQL ibase??-> InterBase msql???-> Mini SQL mssql??-> Microsoft SQL Server oci8???-> Oracle 7/8/8i odbc???-> ODBC (Open Database Connectivity) sybase -> SyBase ifx????-> Informix fbsql??-> FrontBase
|
注意並不是所有數據庫特徵都支持,可以從根目錄>/DB/STATUS 得到詳細的清單。
3.2???????? 執行數據庫
?
// Once you have a valid DB object ... $sql? =? "select * from clients" ; // If the query is a "SELECT", $db->query will return // a DB Result object on success. // Else it simply will return a DB_OK // On failure it will return a DB Error object. $result? =? $db -> query ( $sql ); // Always check that $result is not an error if?( DB :: isError ( $result ))?{ ????????die?( $result -> getMessage ()); } .... ?>
?
|
?
3.3???????? 獲得select的數據
3.3.1?? 獲取數據的函數
?
// Once you have a valid DB Result object ... // Get each row of data on each iteration until // there is no more rows while?( $row? =? $result -> fetchRow ())?{ ???? $id? =? $row [ 0 ]; } ?>
?
|
除了fetchRow()還可以使用fetchInto()直接插入$row的值。
?
... while?( $result -> fetchInto ( $row ))?{ ???? $id? =? $row [ 0 ]; } ?>
?
|
?
3.3.2?? 選擇獲取數據的格式
獲取模式有DB_FETCHMODE_ORDERED(默認), DB_FETCHMODE_ASSOC and DB_FETCHMODE_OBJECT.
從獲取數據方法返回的結果示例:
?
$res? =? $db -> query ( 'select id, name, email from users' ); $row? =? $res -> fetchRow ( $mode ); //With $mode = DB_FETCHMODE_ORDERED //The default behavior is to return an ordered array. $row? =?array?( ???? 0? =>?< column? "id"? data >, ???? 1? =>?< column? "name"? data >, ???? 2? =>?< column? "email"? data > ); $id? =? $row [ 0 ]; //With $mode = DB_FETCHMODE_ASSOC //Returns an associative array with column names as array keys: $row? =?array?( ???? 'id'???? =>?< column? "id"? data >, ???? 'name'?? =>?< column? "name"? data >, ???? 'email'? =>?< column? "email"? data > ); $id? =? $row [ 'id' ]; //With $mode = DB_FETCHMODE_OBJECT //Returns a DB_row object with column names as properties: $row? =? db_row?Object? ( ????[ id ]????=>?< column? "id"? data >, ????[ name ]??=>?< column? "name"? data >, ????[ email ]?=>?< column? "email"? data > ) $id? =? $row -> id ; ?>
?
|
?
3.3.3?? 設置獲取數據的格式
可以使用 fetchrow() / fetchInto() 方法或者爲你的DB實例設置一個默認的模式。
?
... // 1) Set the mode per call: while?( $row? =? $result -> fetchRow ( DB_FETCHMODE_ASSOC ))?{ ????[..] } while?( $result -> fetchInto ( $row ,? DB_FETCHMODE_ASSOC ))?{ ????[..] } // 2) Set the mode for all calls: $db? =? DB :: connect ( $dsn ); // this will set a default fetchmode for this Pear DB instance // (for all queries) $db -> setFetchMode ( DB_FETCHMODE_ASSOC ); $result? =? $db -> query (...); while?( $row? =? $result -> fetchRow ())?{ ???? $id? =? $row [ 'id' ]; } ?>
?
|
?
3.3.4?? 控制獲取數據數量
同時Pear DB獲取數據可以帶有額外的參數,可以使用一個數字參數來獲取需要的數據數量。在你只需要獲得數據中的一部分時這時候特別有用(比如在做分頁程序的時候)
?
... // the row to start fetching $from? =? 50 ; // how many results per page $res_per_page? =? 10 ; // the last row to fetch for this page $to? =? $from? +? $res_per_page ; foreach?( range ( $from ,? $to )?as? $rownum )?{ ????if?(! $row? =? $res -> fetchrow ( $fetchmode ,? $rownum ))?{ ????????break; ????} ???? $id? =? $row [ 0 ]; ????.... } ?>
?
|
?
3.3.5?? 清除結果,釋放變量
當你完成查詢的時候,可以用free()方法來結束:
?
... $result? =? $db -> query ( 'SELECT * FROM clients' ); while?( $row? =? $result -> fetchRow ())?{ ????... } $result -> free (); ?>
?
|
?
3.4???????? 快速retrieve數據
當你不再想用fetchRow()方法來獲取數據的時候,Pear DB通過sql語句提供一些特別的方法來返回想要的數據。這些方法有:getOne, getRow, getCol, getAssoc and getAll. 這有一些使用示例:
?
require_once? 'DB.php' ; $db? =? DB :: connect ( 'pgsql://postgres@unix+localhost/clients_db' ); // ----------------------------------------------------------- // getOne retrieves the first result of the first column // from a query $numrows? =? $db -> getOne ( 'select count(id) from clients' ); // ----------------------------------------------------------- // getRow will fetch the first row and return it as an array $sql? =? 'select name, address, phone from clients where id=1' ; if?( is_array ( $row? =? $db -> getRow ( $sql )))?{ ????list( $name ,? $address ,? $phone )?=? $row ; } // ----------------------------------------------------------- // getCol will return an array with the data of the // selected column. It accepts the column number to retrieve // as the second param. // The next sentence could return for example: // $all_client_names = array('Stig', 'Jon', 'Colin'); $all_client_names? =? $db -> getCol ( 'select name from clients' ); // ----------------------------------------------------------- // Other functions are: getAssoc() and getAll(). // For the moment refer to their in-line documentation // at pear/DB/common.php // ----------------------------------------------------------- ?>
?
|
"get*() 系列方法" 可以爲你做很多事情, 包括: 發起一個查詢, 獲取數據和清除結果。請注意所有的Pear DB函數將可能返回一個 Pear DB_error 對象。
3.5???????? 從查詢結果獲得更多信息(numRows, numCols, affectedRows, tableInfo)
通過 Pear DB可以從查詢結果獲得更多有用的數據信息 。這些方法有:
- numRows(): 通過一個"SELECT" 查詢返回所有數據的數量。
- numCols():通過一個"SELECT" 查詢返回所有的列。
- affectedRows(): 通過("INSERT", "UPDATE" or "DELETE")操作返回所有受影響的數據行數。
- tableInfo():通過一個"SELECT" 查詢返回一個包含數據信息的數組。
示例:
?
... $db? =? DB :: connect ( $dsn ); $sql? =? 'select * from clients' ; $res? =? $db -> query ( $sql ); // Don't forget to check if the returned result from your // action is a Pear Error object. If you get a error message // like 'DB_error: database not capable', means that // your database backend doesn't support this action. // // Number of rows echo? $res -> numRows (); // Number of cols echo? $res -> numCols (); // Table Info print_r? ( $res -> tableInfo ()); // Affected rows $sql? =? "delete from clients" ; // remember that this statement won't return a result object $db -> query ( $sql ); echo? 'I have deleted '? .? $db -> affectedRows ()?.? 'clients' ; ?>
?
|
?
3.6???????? 自動增長(Sequences)
Sequences 爲數據行提供獨一無二的ID標識。如果熟悉MySQL之類的話,可以把它想象爲AUTO_INCREMENT.它非常簡單,首先你獲取一個ID,然後在這個ID所在的行插入你所需要記錄的數據。可以爲你的表設置更多的Sequences,只需要保證在任何特殊的表中都使用一樣的sequence就行。
?
... // Get an ID (if the sequence doesn't exist, it will be created) $id? =? $db -> nextID ( 'mySequence' ); // Use the ID in your INSERT query $res? =? $db -> query ( "INSERT?INTO?myTable?(id,text)?VALUES?($id,'foo')" ); ... ?>
?
|
?
3.7???????? Prepare & Execute/ExcuteMultiple
?
// UNTESTED CODE !!! // // Example inserting data $alldata? =?array( ??array( 1 ,? 'one' ,? 'en' ), ??array( 2 ,? 'two' ,? 'to' ), ??array( 3 ,? 'three' ,? 'tre' ), ??array( 4 ,? 'four' ,? 'fire' ) ); $sth? =? $dbh -> prepare ( "INSERT INTO numbers VALUES(?,?,?)" ); foreach?( $alldata? as? $row )?{ ???? $dbh -> execute ( $sth ,? $row ); } //Here's an example of a file placeholder: $myfile? =? "/tmp/image.jpg" ; $sth? =? $dbh -> prepare ( 'INSERT INTO images (?, &)' ); $dbh -> execute ( $sth ,?array( "this is me" ,? $myfile )); //After I commit a bugfix that I have on my laptop, you can use //parameter arrays in the getXxx methods too: $ver? =? $dbh -> getOne ( "SELECT stableversion FROM packages WHERE name = ?" , ????????????????????array( $package )); ?>
?
|
?
3.8???????? autoCommit, commit and rollback
?
4.??????? 可用方法列表
?
/* * From the DB_(driver) objects */ // get the object with, ie: $db? =? DB :: connect ( 'mysql://user:pass@localhost/my_db' ); ? // Set options $db -> setErrorHandling (); $db -> setFetchmode (); // Information $db -> affectedRows (); $db -> tableInfo (); // Database manipulation $db -> query (); // Data fetch $db -> nextId (); $db -> getOne (); $db -> getRow (); $db -> getCol (); $db -> getAssoc (); $db -> getAll (); // Place holders and execute related $db -> quote (); $db -> prepare (); $db -> execute (); $db -> executeMultiple (); // Transactions $db -> autoCommit (); $db -> commit (); $db -> rollback (); // Disconnection $db -> disconnect (); ? /* * From DB_result objects */ // get the object with, ie: $res? =? $db -> query ( 'select * from foo' ); ? // Data fetch $res -> fetchRow (); $res -> fetchInto (); // Result Info $res -> numCols (); $res -> numRows (); $res -> tableInfo (); // Free $res -> free (); ? /* * From DB_error objects */ // get the object with, ie: $error? =? $db -> query ( 'select * from no_table' ); ? $error -> getMessage (); $error -> getDebugInfo (); $error -> toString (); ?>
?
|
?
5.??????? 錯誤處理機制
5.1.?????? 從Pear DB Error獲得錯誤信息
所有從Pear DB 返回的錯誤都是Pear Errors. 這有一種方法來蒐集:
?
... $res? =? $db -> query ( 'select * from no_table' ); if?( DB :: isError ( $res ))?{ ???? // get the portable error string ???? echo? $res -> getMessage (); } ?>
?
|
?
4.2?????????? Debug Pear DB Errors
Pear DB採用一種輕便的錯誤消息系統向用戶報錯。把錯誤信息簡單翻譯成其它語言或者對於一種特殊錯誤採取特殊的處理方式這都帶來了很大的優點。但是對於開發人員來說這些提示並麼有提供很有用的信息。想要得到真實的數據處理出錯的信息,你可以使用getDebugInfo()方法:
?
$sql? =? 'select * from no_table' ; if?( DB :: isError ( $res? =? $db -> query ( $sql )))?{ ???? // get the native backend error ????// and the last query ???? echo? $res -> getDebugInfo (); } ?>
?
|
通過當一個PHP函數出錯時,會打印出出錯提示。在pear中的這種機制被屏蔽了。但時有時你可能需要在代碼中捕捉一些錯誤信息。可以使用set_error_handler PHP 函數, 從 PHP Manual獲取信息.簡單示例:
?
// what messages to report error_reporting? ( E_ALL? ^? E_NOTICE ); // this function will handle all reported errors function? my_error_handler? ( $errno ,? $errstr ,? $errfile ,? $errline )?{ ????echo? "In?$errfile,?line:?$errline /n $errstr"
; } set_error_handler? ( 'my_error_handler' ); $db? =? DB :: connect ( 'pgsql://postgres@localhost/no_db' ); ... ?>
?
|
?
5.3?? 對錯誤採取自動處理
?????? 正如你所看見的, Pear DB提供了廣泛的錯誤檢測和報告機制,這強迫開發人員必需對返回的數據結果進行檢查,是否有錯。 Pear DB同時照顧我們避免這種痛苦的工作,提供了一種靈活的體系,在一個錯誤出現的時候自動調用相應的措施。
這些可能的措施包括:
- 返回錯誤對象 (PEAR_ERROR_RETURN). 這是默認的.
- 打印錯誤 (PEAR_ERROR_PRINT)
- 打印錯誤信息並忽略執行(PEAR_ERROR_DIE)
- 用PHP函數 trigger_error()來列舉錯誤(PEAR_ERROR_TRIGGER)
- 把錯誤對象傳遞給一個函數或者類的方法 (PEAR_ERROR_CALLBACK)
簡單示例:
?
require_once? 'DB.php' ; // Set the default action to take on error PEAR :: setErrorHandling ( PEAR_ERROR_DIE ); // From here you don't need to check errors any more $db? =? DB :: connect ( 'pgsql://postgres@localhost/my_database' ); $res? =? $db -> query ( 'select id from no_table' ); // at this point the execution is aborted and the error message is raisen ... ?>
?
|
高級示例:
?
// Define the app environment (this is: what errors you want to output) define? ( 'DEBUG_ENV' ,? true ); // This function will handle all errors function? handle_pear_error? ( $error_obj )?{ ???? // Be verbose while developing the application ???? if?( DEBUG_ENV )?{ ????????die?( $error_obj -> getMessage (). "/n" . $error_obj -> getDebugInfo ()); ???? // Dump a silly message if the site is in production ???? }?else?{ ????????die?( 'Sorry you request can not be processed now. Try again later' ); ????} } require_once? 'DB.php' ; // On error, call the "handle_pear_error" function back // You can also use an object as pear error handler so: // setErrorHandling(PEAR_ERROR_CALLBACK, array($object,'method_name'); PEAR :: setErrorHandling ( PEAR_ERROR_CALLBACK ,? 'handle_pear_error' ); $db? =? DB :: connect ( 'pgsql://postgres@localhost/site_db' ); $res? =? $db -> query ( 'select id from no_table' ); // at this point the execution is aborted and the "handle_pear_error" // function is called with the error object as its first argument while?( $row? =? $res -> fetchRow ())?{ ????... } ... ?>
?
|
下面爲擴展錯誤機制提供了一個很好的想法:
?
error_reporting? ( E_ALL? ^? E_NOTICE ); // this function will handle all errors reported by PHP function? php_error_handler? ( $errno ,? $errstr ,? $errfile ,? $errline )?{ ????die?( "In?$errfile,?line:?$errline /n $errstr"
); } set_error_handler? ( 'php_error_handler' ); // this function will catch errors generated by Pear, // transform it to PHP errors and trigger them to the php_error_handler function? pear_error_handler? ( $err_obj )?{ ???? $error_string? =? $err_obj -> getMessage ()?.? ' '? .? $error_obj -> getDebugInfo (); ???? trigger_error? ( $error_string ,? E_USER_ERROR ); } require? 'DB.php' ; PEAR :: setErrorHandling? ( PEAR_ERROR_CALLBACK ,? 'pear_error_handler' ); // force an error $db? =? DB :: connect ( 'pgsql://postgres@localhost/no_db' ); ... ?>
?
|