Zend_Db_Adapter 是 zendframework 的數據庫抽象層 API,基於 pdo,你可以使用 Zend_Db_Adapter 連接和處理多種數據庫,包括 microsoft SQL Server,MySql,SQLite 等等。要針對不同的數據庫實例化一個 Zend_Db_Adapter 對象,需要將 adapter 的名字和描述數據庫連接的參數數組作為參數,靜態調用 Zend_Db::factory() 方法。例如,連接到一個數據庫名稱為"test",用戶名為"root"的本地 MySQL 數據庫,可以進行如下操作:
<?php require_once 'Zend/Db.php'; $params = array ( 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'test' ); $db = Zend_Db::factory('PDO_MYSQL', $params); ?>
一旦你得到了一個 Zend_Db_Adapter 實例,你可以直接執行 sql 語句進行查詢。Zend_Db_Adapter 傳送這些 sql 語句到底層的 PDO 對象,由PDO 對象組合並執行他們,在有查詢結果的情況下,返回一個 PDOStatement 對象以便對結果進行處理。
數據庫如下:
id name 1 A 2 B 3 C 4 DPHP代碼:
<?php require_once 'Zend/Db.php'; $params = array ( 'host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'test' ); $db = Zend_Db::factory('PDO_MYSQL', $params); // 創建一個$db 對象,然後查詢數據庫 // 使用完整的sql 語句直接進行查詢. $sql = $db->quoteInto( 'SELECT * FROM test WHERE id = ?', '3' ); $result = $db->query($sql); // 使用PDOStatement 對象$result 將所有結果數據放到一個數組中 $rows = $result->fetchAll(); ?> <pre> <?php print_r($rows); ?> </pre>
程序運行結果:
Array ( [0] => Array ( [id] => 3 [name] => C ) )
你可以將數據自動的綁定到你的查詢中。這意味著你在查詢中可以設定多個指定的占位符,然後傳送一個數組數據以代替這些占位符。這些替換的數據是自動進行加引號處理的,為防止數據庫攻擊提供了更強的安全性。
<?php // 創建一個$db 對象,然後查詢數據庫. // 這一次,使用綁定的占位符. $result = $db->query( 'SELECT * FROM example WHERE date > :placeholder', array('placeholder' => '2006-01-01') ); // 使用PDOStatement 對象$result 將所有結果數據放到一個數組中 $rows = $result->fetchAll(); ?>
或者,你也可以手工設置 sql 語句和綁定數據到 sql 語句。這一功能通過 prepare() 方法得到一個設定好的PDOStatement 對象,以便直接進行數據庫操作。
<?php // 創建一個$db 對象,然後查詢數據庫. // 這次, 設定一個PDOStatement 對象進行手工綁定. $stmt = $db->prepare('SELECT * FROM example WHERE date > :placeholder'); $stmt->bindValue('placeholder', '2006-01-01'); $stmt->execute(); // 使用PDOStatement 對象$result 將所有結果數據放到一個數組中 $rows = $stmt->fetchAll(); ?>
默認情況下,PDO(因此Zend_Db_Adapter 也是)是采用自動 commit 模式。也就是說,所有的數據庫操作執行時就做了 commit 操作。假如你試圖執行事務處理,最簡單的是調用 beginTransaction() 方法,然後選擇 commit 或者 rollback。之後,Zend_Db_Adapter 會回到自動 commit 模式下,直到你再次調用 beginTransaction() 方法。
<?php // 創建一個$db 對象, 然後開始做一個事務處理. $db->beginTransaction(); // 嘗試數據庫操作. // 假如成功,commit 該操作; // 假如, roll back. try { $db->query(...); $db->commit(); } catch (Exception $e) { $db->rollBack(); echo $e->getMessage(); } ?>
為了方便起見,你可以使用 insert() 方法將要插入的數據綁定並創建一個 insert 語句(綁定的數據是自動進行加引號處理以避免數據庫攻擊的)返回值並不是最後插入的數據的id,這樣做的原因在於一些表並沒有一個自增的字段;相反的,這個插入的返回值是改變的數據行數(通常情況為1)。假如你需要最後插入的數據id,可以在 insert 執行後調用lastInsertId()方法。
<?php// // INSERT INTO round_table // (noble_title, first_name, favorite_color) // VALUES ("King", "Arthur", "blue"); // // 創建一個$db 對象, 然後... // 以"列名"=>"數據"的格式格式構造插入數組,插入數據行 $row = array ( 'noble_title' => 'King', 'first_name' => 'Arthur', 'favorite_color' => 'blue', ); // 插入數據的數據表 $table = 'round_table'; // i 插入數據行並返回行數 $rows_affected = $db->insert($table, $row); $last_insert_id = $db->lastInsertId(); ?>
為了方便起見,你可以使用 update() 方法確定需要 update 的數據並且創建一個 update 語句(確定的數據是自動加引號處理以避免數據庫攻擊的)。你可以提供一個可選的 where 語句說明 update 的條件(注意:where 語句並不是一個綁定參數,所以你需要自己數據進行加引號的操作)。
<?php // UPDATE round_table // SET favorite_color = "yellow" // WHERE first_name = "Robin"; // 創建一個$db 對象, 然後... // 以"列名"=>"數據"的格式構造更新數組,更新數據行 $set = array ( 'favorite_color' => 'yellow', ); // 更新的數據表 $table = 'round_table'; // where 語句 $where = $db->quoteInto('first_name = ?', 'Robin'); // 更新表數據,返回更新的行數 $rows_affected = $db->update($table, $set, $where); ?>
為了方便起見,你可以使用 delete() 方法創建一個 delete 語句;你也可以提供一個 where 語句以說明數據的刪除條件。(注意:where 語句並不是一個綁定參數,所以你需要自己進行數據加引號處理)。
<?php // 需要刪除數據的表 // WHERE first_name = "Patsy"; // 創建一個$db 對象, 然後... // 設定需要刪除數據的表 $table = 'round_table'; // where 條件語句 $where = $db->quoteInto('first_name = ?', 'Patsy'); // 刪除數據並得到影響的行數 $rows_affected = $db->delete($table, $where); ?>
盡管你可以使用 query() 方法直接對數據庫進行操作,但是通常情況下,仍然還是需要選擇數據行並返回結果。以 fetch 開頭的一系列的方法可以實現這個要求。對於每一種 fetch 系列的方法來說,你需要傳送一個 select 的 sql 語句;假如你在操作語句中使用指定的占位符,你也可以傳送一個綁定數據的數組對你的操作語句進行處理和替換。Fetch 系列的方法包括:
<?php // 創建一個$db 對象, 然後... // 取回結果集中所有字段的值,作為連續數組返回 $result = $db->fetchAll( "SELECT * FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // 取回結果集中所有字段的值,作為關聯數組返回 // 第一個字段作為碼 $result = $db->fetchAssoc( "SELECT * FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // 取回所有結果行的第一個字段名 $result = $db->fetchCol( "SELECT first_name FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // 只取回第一個字段值 $result = $db->fetchOne( "SELECT COUNT(*) FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // 取回一個相關數組,第一個字段值為碼 // 第二個字段為值 $result = $db->fetchPairs( "SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // 只取回結果集的第一行 $result = $db->fetchRow( "SELECT * FROM round_table WHERE first_name = :name", array('name' => 'Lancelot') ); ?>
你應該處理將在 sql 語句中使用的條件值;這對於防止 sql 語句攻擊是很有好處的。Zend_Db_Adapter (通過pdo)提供了兩種方法幫助你手動的為條件值加上引號。第一種是 quote() 方法。該方法會根據數據庫 adapter 為標量加上合適的引號;假如你試圖對一個數組做 quote 操作,它將為數組中每個元素加上引號,並用","分隔返回。 (對於參數很多的函數來說,這點是很有幫助的)。
<?php // 創建一個$db 對象,假設數據庫adapter 為mysql. // 為標量加引號 $value = $db->quote('St John"s Wort'); // $value 現在變成了'"St John\"s Wort"' (注意兩邊的引號) // 為數組加引號 $value = $db->quote(array('a', 'b', 'c'); // $value 現在變成了'"a", "b", "c"' (","分隔的字符串) ?>
第二種是 quoteInto() 方法,你提供一個包含問號占位符的基礎字符串,然後在該位置加入帶引號的標量或者數組。該方法對於隨需構建查詢 sql 語句和條件語句是很有幫助的。使用 quoteInto 處理過的標量和數組返回結果與 quote() 方法相同。
<?php // 創建一個$db 對象,假設數據庫adapter 為mysql. // 在where 語句中為標量加上引號 $where = $db->quoteInto('id = ?', 1); // $where 現在為'id = "1"' (注意兩邊的引號) // 在where 語句中為數組加上引號 $where = $db->quoteInto('id IN(?)', array(1, 2, 3)); // $where 現在為'id IN("1", "2", "3")' (一個逗號分隔的字符串) ?>