本來要把預處理語句和前面的基礎操作寫成一篇的。但是,由於博客園的限制,可能是因為長度超出,保存時總是報錯,於是再開一篇。另一方面,相較於前面的exec()和query()語句來說,預處理語句更加常用
在生成網頁時,許多PHP腳本通常都會執行除參數之外,其他部分完全相同的查詢語句,針對這種重復執行一個查詢,每次迭代使用不同的參數情況,PDO提供了一種名為預處理語句(prepared statement)的機制。它可以將整個SQL命令向數據庫服務器發送一次,以後只有參數發生變化,數據庫服務器只需對命令的結構做一次分析就夠了,即編譯一次,可以多次執行。會在服務器上緩存查詢的語句和執行過程,而只在服務器和客戶端之間傳輸有變化的列值,以此來消除這些額外的開銷。這不僅大大減少了需要傳輸的數據量,還提高了命令的處理效率。可以有效防止SQL注入,在執行單個查詢時快於直接使用query()或exec()的方法,速度快且安全,推薦使用
PDO對預處理語句的支持需要使用PDOStatement類對象,但該類的對象並不是通過NEW關鍵字實例化出來的,而是通過執行PDO對象的prepare()方法,在數據庫服務器中准備好一個預處理的SQL語句後直接返回的。如果通過之前執行PDO對象的query()方法返回的PDOStatement類對象,只代表的是一個結果集對象。而如果通過執行PDO對象中的prepare()方法產生的PDOStatement類對象,則為一個查詢對象,能定義和執行參數化的SQL命令
重復執行一個SQL查詢,通過每次迭代使用不同的參數,這種情況使用預處理語句運行效率最高。使用預處理語句,首先需要在數據庫服務器中先准備好“一個SQL語句”,但並不需要馬上執行。PDO支持使用“占位符”語法,將變量綁定到這個預處理的SQL語句中。另外,PDO幾乎為所支持的所有數據庫提供了命令占位符模擬,甚至可以為生來就不支持該概念的數據庫模擬預處理語句和綁定參數。這是PHP向前邁進的積極一步,因為這樣可以使開發人員能夠用PHP編寫“企業級”的數據庫應用程序,而不必特別關注數據庫平台的能力
對於一個准備好的SQL語句,如果在每次執行時都要改變一些列值,這種情況必須使用“占位符”而不是具體的列值,或者只要有需要使用變量作為值的地方,就先使用占位符替代,准備好一個沒有傳值的SQL語句,在數據庫服務器的緩存區等待處理,然後再去單獨賦給占位符具體的值,再通過這個准備好的預處理語句執行。在PDO中有兩種使用占位符的語法:“命令參數”和“問號參數”,使用哪一種語法看個人的喜好
使用命名參數作為占位符的INSERT查詢如下所示:
$dbh->prepare("INSERT INTO contactInto(name,address,phone)VALUES (:name,:address,:phone)");
需要自定義一個字符串作為“命名參數”,每個命名參數需要冒號(:)開始,參數的命名一定要有意義,最好和對應的字段名稱相同
使用問號(?)參數作為占位符的INSERT查詢如下所示:
$dbh->prepare("INSERT INTO contactInfo(name,address,phone) VALUES (?,?,?)");
問號參數一定要和字段的位置順序對應,不管是使用哪一種參數作為占位符構成的查詢,或是語句中沒有用到占位符,都需要使用PDO對象中的prepare()方法,去准備這個將要用於迭代執行的查詢,並返回PDOStatement類對象
當SQL語句通過PDO對象中的prepare()方法,在數據庫服務器端准備好之後,如果使用了占位符,就需要在每次執行時替換輸入的參數。可以通過PDOStatement對象中的bindParam()方法,把參數變量綁定到准備好的占位符上(位置或名字要對應)。方法bindParame()的原型如下所示:
bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )
綁定一個PHP變量到用作預處理的SQL語句中的對應命名占位符或問號占位符。不同於 PDOStatement::bindValue(),此變量作為引用被綁定,並只在PDOStatement::execute()被調用的時候才取其值
parameter表示參數標識符(必須項)。對於使用命名占位符的預處理語句,應是類似:name形式的參數名。對於使用問號占位符的預處理語句,應是以1開始索引的參數位置
variable(必須項)表示綁定到 SQL 語句參數的 PHP 變量名
data_type(可選項)表示使用PDO::PARAM_*常量明確地指定參數的類型。要從一個存儲過程中返回一個INOUT參數,需要為data_type參數使用按位或操作符去設置PDO::PARAM_INPUT_OUTPUT位,可以為以下值
PDO:PARAM_BOOL:表示boolean數據類型 PDO:PARAM_NULL:表示NULL數據類型 PDO:PARAM_INT:表示INT數據類型 PDO:PARAM_STR:表示字符串數據類型 PDO:PARAM_LOB:表示大對象數據類型
length(可選項)表示數據類型的長度。為表明參數是一個存儲過程的OUT參數,必須明確地設置此長度
使用bindParam()方法分別綁定上對應的參數。查詢中使用名字參數的綁定如下所示
$query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->bindParam(":name",$name); $stmt->bindParam(":address",$address); $stmt->bindParam(":phone",$phone); $name = '愛新覺羅'; $address = '東城'; $phone = '88888';
查詢中使用問號?參數的綁定如下所示
$query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->bindParam("1",$name); $stmt->bindParam("2",$address); $stmt->bindParam("3",$phone); $name = '司馬'; $address = '西城'; $phone = '666';
當准備好查詢並綁定了相應的參數後,就可以通過調用PDOStatement類對象中的execute()方法,反復執行在數據庫緩存區准備好的語句了。在下面的示例中,向前面提供的contactInfo表中,使用預處理方式連續執行同一個INSERT語句,通過改變不同的參數添加兩條記錄
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->bindParam("1",$name); $stmt->bindParam("2",$address); $stmt->bindParam("3",$phone); $name = '司馬'; $address = '西城'; $phone = '666'; $stmt->execute(); $name = '曹操'; $address = '平谷'; $phone = '1'; $stmt->execute(); ?>
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->bindParam(":name",$name); $stmt->bindParam(":address",$address); $stmt->bindParam(":phone",$phone); $name = '愛新覺羅'; $address = '東城'; $phone = '88888'; $stmt->execute(); ?>
如果只是要傳遞輸入參數,並且有許多這樣的參數要傳遞,那麼通過在execute()方法中提供一個可選參數,該參數是由准備查詢中的命名參數占位符組成的數組,這是第二種為預處理查詢在執行中替換輸入參數的方式。此語法可以活動對bindParam()的調用
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->execute(array("張飛",'延慶','3')); $query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->execute(array(":name"=>"關羽",":address"=>"密雲",":phone"=>"2")); ?>
如果執行的是INSERT語句,並且數據表有自動增長的ID字段,可以使用PDO對象中的lastInsertId()方法獲取最後插入數據表中的記錄ID。如果需要查看其他DML語句是否執行成功,可以通過PDOStatement類對象中的rowCount()方法獲取影響記錄的行數
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->execute(array("孫權",'通州','123456')); echo $dbh->lastInsertId(); $query = "UPDATE contactInfo SET name=? WHERE uid=?"; $stmt = $dbh->prepare($query); $stmt->execute(array("天使","6")); echo $stmt->rowCount();//1 $query = "DELETE FROM contactInfo WHERE name= ?"; $stmt = $dbh->prepare($query); $stmt->execute(["孫權"]); echo $stmt->rowCount();//11 ?>
PDO的數據獲取方法與其他數據庫擴展都非常類似,只要成功執行SELECT查詢,都會有結果集對象生成。不管是使用PDO對象中的query()方法,還是使用prepare()和execute()等方法結合的預處理語句,執行SELECT查詢都會得到相同的結果集對象PDOStatement,都需要通過PDOStatement類對象中的方法將數據遍歷出來
fetch()
PDOStatement類中的fetch()方法可以將結果集中當前行的記錄以某種方式返回,並將結果集指針移到下一行,當到達結果集末尾時返回FALSE,該方法的原型如下:
mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )
第一個參數fetch_style(可選項),用於控制下一行如何返回給調用者。此值必須是 PDO::FETCH_* 系列常量中的一個,缺省為 PDO::ATTR_DEFAULT_FETCH_MODE 的值(默認為 PDO::FETCH_BOTH)
PDO::FETCH_ASSOC:返回一個索引為結果集列名的數組 PDO::FETCH_BOTH(默認):返回一個索引為結果集列名和以0開始的列號的數組 PDO::FETCH_BOUND:返回 TRUE ,並分配結果集中的列值給 PDOStatement::bindColumn() 方法綁定的 PHP 變量。 PDO::FETCH_CLASS:返回一個請求類的新實例,映射結果集中的列名到類中對應的屬性名。如果 fetch_style 包含 PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE),則類名由第一列的值決定 PDO::FETCH_INTO:更新一個被請求類已存在的實例,映射結果集中的列到類中命名的屬性 PDO::FETCH_LAZY:結合使用PDO::FETCH_BOTH和PDO::FETCH_OBJ,創建供用來訪問的對象變量名 PDO::FETCH_NUM:返回一個索引為以0開始的結果集列號的數組 PDO::FETCH_OBJ:返回一個屬性名對應結果集列名的匿名對象
第二個參數cursor_orientation(可選項)表示對於一個PDOStatement對象表示的可滾動游標,該值決定了哪一行將被返回給調用者。此值必須是 PDO::FETCH_ORI_* 系列常量中的一個,默認為 PDO::FETCH_ORI_NEXT。要想讓 PDOStatement 對象使用可滾動游標,必須在用 PDO::prepare() 預處理SQL語句時,設置 PDO::ATTR_CURSOR 屬性為 PDO::CURSOR_SCROLL
第三個參數offset(可選項)表示對於一個cursor_orientation參數設置為PDO::FETCH_ORI_ABS的PDOStatement對象代表的可滾動游標,此值指定結果集中想要獲取行的絕對行號
對於一個 cursor_orientation 參數設置為 PDO::FETCH_ORI_REL 的PDOStatement 對象代表的可滾動游標,此值指定想要獲取行相對於調用 PDOStatement::fetch() 前游標的位置
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); //Array ( [uid] => 1 [0] => 1 [name] => 張三 [1] => 張三 [address] => 朝陽 [2] => 朝陽 [phone] => 123 [3] => 123 [email] => [email protected] [4] => [email protected] ) print_r($stmt->fetch()); echo "<br>"; //Array ( [uid] => 2 [0] => 2 [name] => 李四 [1] => 李四 [address] => 朝陽 [2] => 朝陽 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) print_r($stmt->fetch()); echo "<br>"; ?>
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); /* Array ( [0] => 1 [1] => 張三 [2] => 朝陽 [3] => 123 [4] => [email protected] ) Array ( [0] => 2 [1] => 李四 [2] => 朝陽 [3] => 123456789 [4] => [email protected] ) Array ( [0] => 3 [1] => 王五 [2] => 海澱 [3] => 15011113456 [4] => [email protected] ) Array ( [0] => 4 [1] => 趙四 [2] => 海澱 [3] => 123456789 [4] => [email protected] ) Array ( [0] => 5 [1] => 諸葛 [2] => [3] => 120120120 [4] => [email protected] ) Array ( [0] => 6 [1] => 天使 [2] => [3] => 222 [4] => [email protected] ) Array ( [0] => 7 [1] => 司馬 [2] => 西城 [3] => 666 [4] => ) Array ( [0] => 8 [1] => 曹操 [2] => 平谷 [3] => 1 [4] => ) Array ( [0] => 9 [1] => 愛新覺羅 [2] => 東城 [3] => 88888 [4] => ) Array ( [0] => 10 [1] => 張飛 [2] => 延慶 [3] => 3 [4] => ) Array ( [0] => 11 [1] => 關羽 [2] => 密雲 [3] => 2 [4] => ) */ while($row = $stmt->fetch(PDO::FETCH_NUM)){ print_r($row); echo "<br>"; } ?>
下面以表格的形式輸出結果集
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; while(list($uid, $name, $address, $phone, $email) = $stmt -> fetch(PDO::FETCH_NUM)) { echo '<tr>'; echo '<td>'.$uid.'</td>'; echo '<td>'.$name.'</td>'; echo '<td>'.$address.'</td>'; echo '<td>'.$phone.'</td>'; echo '<td>'.$email.'</td>'; echo '</tr>'; } echo '</table>'; ?>
fetchAll()
fetchAll()方法與上一個方法fetch()類似,但是該方法只需要調用一次就可以獲取結果集中的所有行,並賦給返回的二維數組。該方法的原型如下:
fetchAll([int fetch_style [,int column_index]])
第一個參數fetch_style是可選項,以何種方式引用所獲取的列取決於該參數。默認值為PDO::FETCH_BOTH,所有可用的值可以參考在fetch()方法中介紹的第一個參數的列表,還可以指定PDO::FETCH_COLUMN值,從結果集中返回一個包含單列的所有值
第二個參數column_index是可選項,需要提供一個整數索引,當在fetchAll()方法的第一個參數中指定PDO::FETCH_COLUMN值時,從結果集中返回通過該參數提供的索引所指定列的所有值
/* Array ( [0] => Array ( [uid] => 1 [0] => 1 [name] => 張三 [1] => 張三 [address] => 朝陽 [2] => 朝陽 [phone] => 123 [3] => 123 [email] => [email protected] [4] => [email protected] ) [1] => Array ( [uid] => 2 [0] => 2 [name] => 李四 [1] => 李四 [address] => 朝陽 [2] => 朝陽 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) [2] => Array ( [uid] => 3 [0] => 3 [name] => 王五 [1] => 王五 [address] => 海澱 [2] => 海澱 [phone] => 15011113456 [3] => 15011113456 [email] => [email protected] [4] => [email protected] ) [3] => Array ( [uid] => 4 [0] => 4 [name] => 趙四 [1] => 趙四 [address] => 海澱 [2] => 海澱 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) [4] => Array ( [uid] => 5 [0] => 5 [name] => 諸葛 [1] => 諸葛 [address] => [2] => [phone] => 120120120 [3] => 120120120 [email] => [email protected] [4] => [email protected] ) [5] => Array ( [uid] => 6 [0] => 6 [name] => 天使 [1] => 天使 [address] => [2] => [phone] => 222 [3] => 222 [email] => [email protected] [4] => [email protected] ) [6] => Array ( [uid] => 7 [0] => 7 [name] => 司馬 [1] => 司馬 [address] => 西城 [2] => 西城 [phone] => 666 [3] => 666 [email] => [4] => ) [7] => Array ( [uid] => 8 [0] => 8 [name] => 曹操 [1] => 曹操 [address] => 平谷 [2] => 平谷 [phone] => 1 [3] => 1 [email] => [4] => ) [8] => Array ( [uid] => 9 [0] => 9 [name] => 愛新覺羅 [1] => 愛新覺羅 [address] => 東城 [2] => 東城 [phone] => 88888 [3] => 88888 [email] => [4] => ) [9] => Array ( [uid] => 10 [0] => 10 [name] => 張飛 [1] => 張飛 [address] => 延慶 [2] => 延慶 [phone] => 3 [3] => 3 [email] => [4] => ) [10] => Array ( [uid] => 11 [0] => 11 [name] => 關羽 [1] => 關羽 [address] => 密雲 [2] => 密雲 [phone] => 2 [3] => 2 [email] => [4] => ) ) */ print_r($stmt->fetchAll());
下面以表格的形式輸出結果集
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; $allRows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach($allRows as $row){ echo '<tr>'; echo '<td>'.$row['uid'].'</td>'; echo '<td>'.$row['name'].'</td>'; echo '<td>'.$row['address'].'</td>'; echo '<td>'.$row['phone'].'</td>'; echo '<td>'.$row['email'].'</td>'; echo '</tr>'; } echo '</table>'; ?>
下面使用fetchAll()方法輸出所有的姓名數組
$query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $row=$stmt->fetchAll(PDO::FETCH_COLUMN,1); echo '所有聯系人的姓名:'; //所有聯系人的姓名:Array ( [0] => 張三 [1] => 李四 [2] => 王五 [3] => 趙四 [4] => 諸葛 [5] => 天使 [6] => 司馬 [7] => 曹操 [8] => 愛新覺羅 [9] => 張飛 [10] => 關羽 ) print_r($row);
setFetchMode()
PDOStatement對象中的fetch()和fetchAll()兩個方法,獲取結果數據的引用方式默認是一樣的,既按列名索引又按列在行中的數值偏移(從0開始)索引的值數組,因為它們的默認模式都被設置為PDO::FETCH_BOTH值,如果計劃使用其他模式來改變這個默認設置,可以在fetch()或fetchAll()方法中提供需要的模式參數。但如果多次使用這兩個方法,在每次調用時都需要設置新的模式來改變默認的模式。這時就可以使用PDOStatement類對象中的setFetchMode()方法,在腳本頁面的頂部設置一次模式,以後所有fetch()和fetchAll()方法的調用都將生成相應引用的結果集,減少了多次在調用fetch()方法時的參數錄入
$query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $stmt->setFetchMode(PDO::FETCH_ASSOC); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; $allRows = $stmt->fetchAll(); foreach($allRows as $row){ echo '<tr>'; echo '<td>'.$row['uid'].'</td>'; echo '<td>'.$row['name'].'</td>'; echo '<td>'.$row['address'].'</td>'; echo '<td>'.$row['phone'].'</td>'; echo '<td>'.$row['email'].'</td>'; echo '</tr>'; } echo '</table>';
bindColumn()
使用該方法可以將一個列和一個指定的變量名綁定,這樣在每次使用fetch()方法獲取各行記錄時,會自動將相應的列值賦給該變量,但必須是在fetch()方法的第一個參數設置為PDO::FETCH_BOTH值時。bindColumn()方法的原型如下所示:
bindColumn(mixed column,mixed $param[,int type]);//設置綁定列值到變量上
第一個參數column為必選項,可以使用整數的列偏移位置索引(索引值從1開始),或是列的名稱字符串。第二個參數param也是必選項,需要傳遞一個引用,所以必須提供一個相應的變量名。第三個參數type是可選項,通過設置變量的類型來限制變量值,該參數支持的值和介紹bindParam()方法時提供的一樣
<?php try { //創建對象 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "數據庫連接失敗:".$e->getMessage(); exit; } $query = "SELECT * FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $stmt->bindColumn(1,$uid); $stmt->bindColumn(2,$name); $stmt->bindColumn(3,$departmentID); $stmt->bindColumn('address',$address); $stmt->bindColumn('phone',$phone); $stmt->bindColumn(6,$email); $stmt->setFetchMode(PDO::FETCH_ASSOC); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>部門</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; while($stmt->fetch()){ echo '<tr>'; echo '<td>'.$uid.'</td>'; echo '<td>'.$name.'</td>'; echo '<td>'.$departmentID.'</td>'; echo '<td>'.$address.'</td>'; echo '<td>'.$phone.'</td>'; echo '<td>'.$email.'</td>'; echo '</tr>'; } echo '</table>'; ?>
除了可以通過上面幾種方式獲取數據表中記錄信息外,還可以使用PDOStatement類對象的columnCount()方法獲取數據表中字段的數量,並且可以通過PDOStatement類對象的getColumnMeta()方法獲取具體列的屬性信息
PDOStatement::getColumnMeta
PDOStatement::getColumnMeta — 返回結果集中一列的元數據。參數column表示結果集中以0開始索引的列
array PDOStatement::getColumnMeta ( int $column )
$query = "SELECT * FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo $stmt->columnCount();//6 /* array (size=7) 'native_type' => string 'INT24' (length=5) 'pdo_type' => int 2 'flags' => array (size=2) 0 => string 'not_null' (length=8) 1 => string 'primary_key' (length=11) 'table' => string 'contactInfo' (length=11) 'name' => string 'uid' (length=3) 'len' => int 8 'precision' => int 0 */ var_dump($stmt->getColumnMeta(0));
在進行項目開發時,有時會需要在數據庫中在存儲“大型”數據。大型對象可以是文本數據,也可以是二進制的圖片、電影等。PDO允許在bindParam()或bindColumn()調用中通過使用PDO::PARAM_LOB類型代碼來使用大型數據類型。PDO::PARAM_LOB告訴PDO將數據映射為流,所以可以使用PHP中的文件處理函數來操縱這樣的數據
下面將上傳的圖像插入到一個數據庫
$stmt =$dbh->prepare("insert into images(mimetype, data) values(?, ?)"); $stmt->bindParam(1, $_FILES['pic']['type']); $fp = fopen($_FILES['pic']['tmp_name'], "rb"); //直接使用文件資源就可以入庫,而不用讀出文件,再插入 $stmt->bindparam(2, $fp, PDO::PARAM_LOB); $stmt->execute(); fclose($fp);
下面從數據庫中讀出一幅圖像
$stmt = $dbh->prepare("select mimetype, data from images where id=?"); $stmt -> execute(array(1)); list($mimetype, $data) = $stmt->fetch(PDO::FETCH_NUM); header("Content-Type: {$mimetype}"); echo $data;