上一節,大概了解了Zend Framework完成數據庫操作的常用類,下面一一簡單介紹其用法。
Zend_Db_Adapter是我們操作數據庫的常用方式,以下是幾個比較重要的功能使用說明:
1.建立數據庫鏈接
require_once 'Zend/Db.php'; $params = array ('host' => '127.0.0.1', 'username' => 'root', 'password' => '', 'dbname' => 'test'); $db = Zend_Db::factory('PDO_MYSQL', $params);
public static function factory($adapter, $config = array())
第一個參數是采用何種方式鏈接。
第二個參數是指定傳遞的鏈接參數。
我們采用的是‘PDO_MYSQL’連接方式。具體參數規則如下:
/* * Form full adapter class name */ $adapterNamespace = 'Zend_Db_Adapter'; if (isset($config['adapterNamespace'])) { if ($config['adapterNamespace'] != '') { $adapterNamespace = $config['adapterNamespace']; } unset($config['adapterNamespace']); } // Adapter no longer normalized- see http://framework.zend.com/issues/browse/ZF-5606 $adapterName = $adapterNamespace . '_'; $adapterName .= str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapter)))); /* * Load the adapter class. This throws an exception * if the specified class cannot be loaded. */ if (!class_exists($adapterName)) { require_once 'Zend/Loader.php'; Zend_Loader::loadClass($adapterName); }
以下是常見的方式,取Zend_Db_Adapter_后面的名字作為參數。
Zend_Db_Adapter_Pdo_Sqlite
Zend_Db_Adapter_Pdo_Pgsql
Zend_Db_Adapter_Pdo_Mssql
Zend_Db_Adapter_Mysqli
Zend_Db_Adapter_Db2
Zend_Db_Adapter_Oracle
Zend_Db_Adapter_Sqlsrv
具體的配置參數可以使用查看Zend_Db_Adapter_Abstract源碼的$config。當然你可以把配置參數放到application.ini配置文件,這里不再累述。
具體的實現方法如下:
/** * Factory for Zend_Db_Adapter_Abstract classes. * * First argument may be a string containing the base of the adapter class * name, e.g. 'Mysqli' corresponds to class Zend_Db_Adapter_Mysqli. This * name is currently case-insensitive, but is not ideal to rely on this behavior. * If your class is named 'My_Company_Pdo_Mysql', where 'My_Company' is the namespace * and 'Pdo_Mysql' is the adapter name, it is best to use the name exactly as it * is defined in the class. This will ensure proper use of the factory API. * * First argument may alternatively be an object of type Zend_Config. * The adapter class base name is read from the 'adapter' property. * The adapter config parameters are read from the 'params' property. * * Second argument is optional and may be an associative array of key-value * pairs. This is used as the argument to the adapter constructor. * * If the first argument is of type Zend_Config, it is assumed to contain * all parameters, and the second argument is ignored. * * @param mixed $adapter String name of base adapter class, or Zend_Config object. * @param mixed $config OPTIONAL; an array or Zend_Config object with adapter parameters. * @return Zend_Db_Adapter_Abstract * @throws Zend_Db_Exception */ public static function factory($adapter, $config = array()) { if ($config instanceof Zend_Config) { $config = $config->toArray(); } /* * Convert Zend_Config argument to plain string * adapter name and separate config object. */ if ($adapter instanceof Zend_Config) { if (isset($adapter->params)) { $config = $adapter->params->toArray(); } if (isset($adapter->adapter)) { $adapter = (string) $adapter->adapter; } else { $adapter = null; } } /* * Verify that adapter parameters are in an array. */ if (!is_array($config)) { /** * @see Zend_Db_Exception */ require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception('Adapter parameters must be in an array or a Zend_Config object'); } /* * Verify that an adapter name has been specified. */ if (!is_string($adapter) || empty($adapter)) { /** * @see Zend_Db_Exception */ require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception('Adapter name must be specified in a string'); } /* * Form full adapter class name */ $adapterNamespace = 'Zend_Db_Adapter'; if (isset($config['adapterNamespace'])) { if ($config['adapterNamespace'] != '') { $adapterNamespace = $config['adapterNamespace']; } unset($config['adapterNamespace']); } // Adapter no longer normalized- see http://framework.zend.com/issues/browse/ZF-5606 $adapterName = $adapterNamespace . '_'; $adapterName .= str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapter)))); /* * Load the adapter class. This throws an exception * if the specified class cannot be loaded. */ if (!class_exists($adapterName)) { require_once 'Zend/Loader.php'; Zend_Loader::loadClass($adapterName); } /* * Create an instance of the adapter class. * Pass the config to the adapter class constructor. */ $dbAdapter = new $adapterName($config); /* * Verify that the object created is a descendent of the abstract adapter type. */ if (! $dbAdapter instanceof Zend_Db_Adapter_Abstract) { /** * @see Zend_Db_Exception */ require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception("Adapter class '$adapterName' does not extend Zend_Db_Adapter_Abstract"); } return $dbAdapter; }
2.常見的方法
主要在Zend_Db_Adapter_Abstract抽象父類和具體的實現類。
以pdo方式的mysql文件,說明常用的功能:
<?phpabstract class Zend_Db_Adapter_Abstract{ public function query($sql, $bind = array()) public function beginTransaction() public function commit() public function rollBack() public function insert($table, array $bind) public function update($table, array $bind, $where = '') public function delete($table, $where = '') public function select() public function getFetchMode() public function fetchAll($sql, $bind = array(), $fetchMode = null) public function fetchRow($sql, $bind = array(), $fetchMode = null) public function fetchAssoc($sql, $bind = array()) public function fetchCol($sql, $bind = array()) public function fetchPairs($sql, $bind = array()) public function fetchOne($sql, $bind = array()) public function quote($value, $type = null) public function quoteInto($text, $value, $type = null, $count = null) public function quoteIdentifier($ident, $auto=false) public function quoteColumnAs($ident, $alias, $auto=false) public function quoteTableAs($ident, $alias = null, $auto = false) }
<?phpabstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract{ public function isConnected() public function closeConnection() public function prepare($sql) public function lastInsertId($tableName = null, $primaryKey = null) public function query($sql, $bind = array()) public function exec($sql) public function setFetchMode($mode) public function supportsParameters($type) public function getServerVersion() }
<?phpclass Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract{ public function limit($sql, $count, $offset = 0)}
3.常見的方法的使用舉例
你應該處理將在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")' (一個逗號分隔的字符串)?>
一旦你得到了一個Zend_Db_Adapter
實例, 你可以直接 執行sql語句進行查詢.Zend_Db_Adapter
傳送這些sql語 句到底層的PDO對象,由PDO對象組合并執行他們,在有查詢結果的情況 下,返回一個PDOStatement對象以便對結果進行處理。
<?php// 創建一個$db對象,然后查詢數據庫// 使用完整的sql語句直接進行查詢.$sql = $db->quoteInto( 'SELECT * FROM example WHERE date > ?', '2006-01-01');$result = $db->query($sql);// 使用PDOStatement對象$result將所有結果數據放到一個數組中$rows = $result->fetchAll();?>
你可以將數據自動的綁定到你的查詢中。這意味著你在查詢中可以設定 多個指定的占位符,然后傳送一個數組數據以代替這些占位符。這些替 換的數據是自動進行加引號處理的,為防止數據庫攻擊提供了更強的安 全性。
<?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系列
的方法包括:
fetchAll()
fetchAssoc()
fetchCol()
fetchOne()
fetchPairs()
fetchRow()
<?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'));?>