PDO最大的特點之一是它的靈活性,本節將介紹如何取得查詢結果,包括:
數組(數值或關聯數組);
字符串(單列的結果集);
對象;
回調函數。
1.快取一行
FetchColumn是爲應用程序取得一個僅包含單列的數據,代碼如下:
$u = $db->query(“SELECT id FROM users WHERE login=‘login’ AND password=‘password’”);
fetch(PDO::FETCH_COLUMN)
if ($u->fetchColumn()) { //返回一個字符串
//登錄成功
} else {
//驗證失敗
}
2.取得一個標準對象
還可以將取得的一行作爲一個標準類stdClass的對象實例,其中列名=屬性名。
$res = $db->query(“SELECT * FROM foo”);
while ($obj = $res->fetch(PDO::FETCH_OBJ)) {
// $obj == instance of stdClass
}
3.存取爲一個類
PDO允許將結果保存爲一個類,例子如下:
$res = $db->query(“SELECT * FROM foo”);
$res->setFetchMode(
PDO::FETCH_CLASS,
“className”,
array(‘optional’=‘Constructor Params’)
);
while ($obj = $res->fetch()) {
// $obj == instance of className
}
4.從一個類取得常量
PDO允許查詢的結果可以被用來生成一個目的類。
$res = $db->query(“SELECT * FROM foo”);
$res->setFetchMode(
PDO::FETCH_CLASS |
PDO::FETCH_CLASSTYPE
);
while ($obj = $res->fetch()) {
// $obj == instance of class who’s name is
// found in the value of the 1st column
}
5.存取爲一個對象
PDO還允許獲取數據到一個已經存在的對象。
$u = new userObject;
$res = $db->query(“SELECT * FROM users”);
$res->setFetchMode(PDO::FETCH_INTO, $u);
while ($res->fetch()) {
// 取得的記錄集將放在$u這個對象變量中,在此顯示
}
6.存取爲關聯數據
PDO實現了迭代器(Iteator)接口,允許一個方法實現迭代的功能。
$res = $db->query(
“SELECT * FROM users”,
PDO::FETCH_ASSOC
);
foreach ($res as $row) {
// $row是一個關聯數組,可以直接顯示,如$row['id']
}
7.fetchAll()方法
PDO也提供了和ADODB類似的fetchAll()方法,它允許從一個結果集中取得數據,然後放於關聯數組中。
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$qry = “SELECT * FROM users”;
$res = $db->query($qry)->fetchAll(PDO::FETCH_ASSOC);
?>
或者獲取到索引數組裏:
$res = $db->query("SELECT * FROM foo");
$result_arr = $res->fetchAll();
print_r($result_arr);
數字索引數組比較浪費資源,請儘量使用關聯數組,這樣可以在內存中使用相當密集的大型結果集。
相關說明如下:
setAttribute()方法用於設置部分屬性,主要屬性有:PDO::ATTR_CASE、PDO::ATTR_ERRMODE等,這裏需要設置的是PDO::ATTR_CASE,就是使用關聯索引獲取數據集時,關聯索引是大寫還是小寫,有如下幾個選擇:
PDO::CASE_LOWER——強制列名是小寫;
PDO::CASE_NATURAL——列名按照原始的方式;
PDO::CASE_UPPER——強制列名爲大寫。
我們使用setFetchMode方法來設置獲取結果集的返回值的數據類型,類型有:
PDO::FETCH_ASSOC——關聯數組形式;
PDO::FETCH_NUM——數字索引數組形式;
PDO::FETCH_BOTH——兩種數組形式都有,這是默認的;
PDO::FETCH_OBJ——按照對象的形式,類似於以前的 mysql_fetch_object()。
當然,一般情況下,我們使用PDO::FETCH_ASSOC取得關聯數組。具體使用哪種類型,應按照自己的實際應用選擇。
8.fetchColumn()方法
如果想獲取指定記錄裏的一個字段結果,則可以使用PDOStatement::fetchColumn()。
$rs = $db->query("SELECT COUNT(*) FROM foo");
$col = $rs->fetchColumn();
echo $col;
一般使用fetchColumn()方法進行count統計,對某些只需要單字段的記錄可以很好地操作。
9.回調函數
PDO還規定在每一個fetch模式下,經過處理後的結果中使用一個回調函數。
function draw_message($subject,$email) { … }
$res = $db->query(“SELECT * FROM msg”);
$res->fetchAll(PDO::FETCH_FUNC,“draw_message”);
10.直接查詢的問題
直接使用Query查詢行每次都會直接提交給數據庫,如果查詢較多,每次頻頻查詢將導致效率降低。
另外,在安全問題上,沒有過濾一些特殊字符容易產生SQL注入。
11.過濾字符
下面我們來看看如何使用PDO進行過濾引起SQL注入的方法,即過濾特殊字符。我們在PDO中使用quote()方法,使用例子如下:
$query = “SELECT * FROM users WHERE
login=“.$db->quote($_POST[‘login’]).”
AND
passwd=“.$db->quote($_POST[‘pass’]);
12.事務處理
PDO驅動程序支持所有的事務數據庫,並且PDO提供更簡便的方法,如下:
$db->beginTransaction();
if ($db->exec($qry) === FALSE) {
$db->rollback();
}
$db->commit();
13.執行一個批處理事務
在下面的示例中,假設我們爲一個新僱員創建一組條目,這個僱員有一個ID號,即23。除了輸入這個僱員的基本數據外,還需要記錄僱員的薪水。分別完成兩個更新很簡單,但通過將這兩個更新包括在beginTransaction()和commit()調用中,就可以保證在更改完成之前,其他人無法看到更改。如果發生了錯誤,catch塊可以回滾事務開始以來發生的所有更改,並打印出一條錯誤消息。代碼內容如下:
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO_ATTR_PERSISTENT => true));
echo "Connected\n";
$dbh->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last)
values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
並不是一定要在事務中做出更新,也可以通過複雜的查詢來提取數據,還可以使用信息構建更多的更新和查詢。當事務在活動時,可以保證其他人在工作進行當中無法做出更改。事實上,這不是100%的正確,但如果您之前沒有聽說過事務的話,這樣介紹也未嘗不可。
下面是一個擴展PDO&PDO語句的類,內容如下:
class Database extends PDO{
function __construct(){
parent::__construct('mysql:dbname=test;host=localhost', 'root', '');
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS,
array('DBStatement'array($this)));
}
}
class DBStatement extends PDOStatement{
public $dbh;
protected function __construct($dbh){
$this->dbh = $dbh;
$this->setFetchMode(PDO::FETCH_OBJ);
}
public function foundRows(){
$rows = $this->dbh->prepare('SELECT found_rows()
AS rows',array(PDO::MYSQL_ATTR_ USE_BUFFERED_QUERY =
> TRUE));
$rows->execute();
$rowsCount = $rows->fetch(PDO::FETCH_OBJ)->rows;
$rows->closeCursor();
return $rowsCount;
}
}
14.存儲過程
在MySQL一章,我們已經瞭解了存儲過程的創建,下面我們來看使用PDO調用的例子:
$stmt = $dbh->prepare("CALL sp_set_string(?)");
$stmt->bindParam(1, $str);
$str = ‘hospinfo’; //綁定參數
$stmt->execute();
與先前講過的綁定例子差不多,只是這裏使用了“?”數據綁定方法,sp_set_string是存儲過程名稱。
帶有輸出參數的存儲過程:
$stmt = $dbh->prepare("CALL sp_get_string(?)");
$stmt->bindParam(1, $ret,PDO:ARAM_STR, 4000);
if ($stmt->execute()) {
echo "返回值 $ret\n";
}
下面是綁定列輸出的腳本例子:
$stmt = $dbh->prepare("SELECT extension, name from CREDITS");
if ($stmt->execute()) {
$stmt->bindColumn('extension', $extension);
$stmt->bindColumn('name', $name);
while ($stmt->fetch(PDO::FETCH_BOUND)) {
echo "Extension: $extension\n";
echo "Author: $name\n";
}
}