搜索
熱搜: 活動 交友 discuz
查看: 3283|回復: 2
打印 上一主題 下一主題

[PHP] [PHP/MySQL] PDO (PHP Data Object) - 入門與基礎教學

[複製鏈接]
跳轉到指定樓層
1#
發表於 2013-9-18 11:44:52 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
PDO(PHP Data Object) 是PHP 5新出來的東西,在PHP 6都要出來的時候,PHP 6只默認使用PDO來處理數據庫,將把所有的數據庫擴展移到了PECL,那麼默認就是沒有了我們喜愛的php_mysql.dll之類的了,那怎麼辦捏, 我們只有與時俱進了,我就小試了一把PDO。(本文為入門級)



  【PDO是啥】

   PDO是PHP 5新加入的一個重大功能,因為在PHP 5以前的php4/php3都是一堆的數據庫擴展來跟各個數據庫的連接和處理,什麼 php_mysql.dll、php_pgsql.dll、php_mssql.dll、php_sqlite.dll等等擴展來連接MySQL、 PostgreSQL、MS SQL Server、SQLite,同樣的,我們必須借助 ADOdb、PEAR::DB、PHPlib::DB之類的數據庫抽象類來幫助我們,無比煩瑣和低效,畢竟,php代碼的效率怎麼能夠我們直接用C/C+ +寫的擴展斜率高捏?所以嘛,PDO的出現是必然的,大家要平靜學習的心態去接受使用,也許你會發現能夠減少你不少功夫哦。

  【安裝PDO】

  我是在Windows XP SP2 上面,所以嘛,整個過程都是在Windows行進行的啦,至於Linux/FreeBSD 等平台,請自行查找資料設置安裝。
我的是PHP 5.1.4,已經自帶有了php_pdo.dll的擴展,不過需要稍微設置一下才能使用。

  打開 c:\windows\php.ini ,那是我的PHP配置文件,找到下面這行:

  extension_dir

  這個就是我們擴展存在的目錄,我的PHP 5擴展是在:C:\php5\ext,那麼我就把這行改成:

  extension_dir = "C:/php5/ext"

  然後再往php.ini下面找到:

  ;;;;;;;;;;;;;;;;;;;;;;
  ; Dynamic Extensions ;
  ;;;;;;;;;;;;;;;;;;;;;;

  下面有一堆類似 ;extension=php_mbstring.dll 的東西,這裡就是PHP擴展加載的配置了,我們再最後面添加上我們PDO的擴展:
  1. extension=php_pdo.dll
  2. extension=php_pdo_mysql.dll
  3. extension=php_pdo_pgsql.dll
  4. extension=php_pdo_sqlite.dll
  5. extension=php_pdo_mssql.dll
  6. extension=php_pdo_odbc.dll
  7. extension=php_pdo_firebird.dll
  8. ;extension=php_pdo_oci8.dll
複製代碼
各種PDO的驅動,能給加上的全給加上,不過後面的php_pdo_oci8.dll,因為我沒有安裝Oralce數據庫,所以沒有這個,就使 用分號註釋掉它。然後重啟我們的Web服務器, IIS/Apache,我的是IIS,嘿嘿,表鄙視我,在Windows上,簡單嘛。

  重啟後,在我們Web服務器的文檔目錄下寫一個phpinfo.php的文件,加上這些:
  1. <?
  2. phpinfo();
  3. ?>
複製代碼
然後打開我們可愛的瀏覽器:IE/FireFox,我的是FireFox 2.0,剛下載的,很爽,不怕流氓軟件,哈哈。

  在瀏覽器裡面輸入:http://localhost/phpinfo.php,如果你的這個頁面路徑不一致,請自行輸入。

  輸出的內容中,如果你能夠順利的看到:
  1. PDO
  2. PDO support enabled
  3. PDO drivers mysql, pgsql, sqlite, mssql, odbc, firebird
複製代碼
後面有各種驅動的說明:PDO_Firebird,pdo_mssql,pdo_mysql,PDO_ODBC,pdo_pgsql,pdo_sqlite

  那麼,恭喜你安裝成功了,否則請仔細檢查上面的步驟。



  【牛刀小小試】

   我用的是MySQL 4.0.26,但是我個人推薦大家使用 MySQL 4.1.x 或者 MySQL 5.0.x,因為那些版本有很多有趣的東西值得去學習。我們這裡PDO需要連接的就是我的MySQL 4.0啦,如果你沒有安裝MySQL,請自行安裝。我們建立好了MySQL,並且在test庫裡添加了表foo,包括 id,name,gender,time等四個字段。

  我們開始構造第一個PDO應用,建立一個pdo.php文件在Web文檔目錄下:
  1. <?php
  2. $dsn = "mysql:host=localhost;dbname=test";
  3. $db = new PDO($dsn, "root","password" );
  4. $count = $db->exec("INSERT INTO foo SET name = 'myname',gender='男',time=NOW()");
  5. echo $count;
  6. $db = null;
  7. ?>
複製代碼
不明白啥意思,俺們來慢慢講講。這行:
  1. $dsn = "mysql:host=localhost;dbname=test";
複製代碼
就是構造我們的DSN(數據源),看看裡面的信息包括:數據庫類型是mysql,主機地址是localhost,數據庫名稱是test,就這麼幾個信息。不同數據庫的數據源構造方式是不一樣的。
  1. $db = new PDO($dsn, root, );
複製代碼
初始化一個PDO對象,構造函數的參數第一個就是我們的數據源,第二個是連接數據庫服務器的用戶,第三個參數是密碼。我們不能保證連接成功,後面我們會講到異常情況,這裡我們姑且認為它是連接成功的。
  1. $count = $db->exec("INSERT INTO foo SET name = heiyeluren,gender=男,time=NOW()");
  2. echo $count;
複製代碼
調用我們連接成功的PDO對象來執行一個查詢,這個查詢是一個插入一條記錄的操作,使用PDO::exec() 方法會返回一個影響記錄的結果,所以我們輸出這個結果。最後還是需要結束對象資源:
  1. $db = null;
複製代碼
默認這個不是長連接,如果需要數據庫長連接,需要最後加一個參數:array(PDO::ATTR_PERSISTENT => true) 變成這樣:
  1. $db = new PDO($dsn, root, , array(PDO::ATTR_PERSISTENT => true));
複製代碼
一次操作就這麼簡單,也許跟以前的沒有太大區別,跟ADOdb倒是有幾分相似。

  【繼續瞭解】

  如果我們想提取數據的話,那麼就應該使用數據獲取功能。(下面用到的$db都是上面已經連接好的對象)
  1. <?php
  2. foreach($db->query("SELECT * FROM foo") as $row){
  3.   print_r($row);
  4. }
  5. ?>
複製代碼
我們也可以使用這種獲取方式:
  1. <?php
  2. $rs = $db->query("SELECT * FROM foo");
  3. while($row = $rs->fetch()){
  4.   print_r($row);
  5. }
  6. ?>
複製代碼
如果想一次把數據都獲取到數組裡可以這樣:
  1. <?php
  2. $rs = $db->query("SELECT * FROM foo");
  3. $result_arr = $rs->fetchAll();
  4. print_r($result_arr);
  5. ?>
複製代碼
  1. Array
  2. ([0] => Array(
  3. [id] => 1
  4. [0] => 1
  5. [name] => myname
  6. [1] => myname
  7. [gender] => 男
  8. [2] => 男
  9. [time] => 2006-10-28 23:14:23
  10. [3] => 2006-10-28 23:14:23
  11. )
  12. }
複製代碼
我們看裡面的記錄,數字索引和關聯索引都有,浪費資源,我們只需要關聯索引的:
  1. <?php
  2. $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
  3. $rs = $db->query("SELECT * FROM foo");
  4. $rs->setFetchMode(PDO::FETCH_ASSOC);
  5. $result_arr = $rs->fetchAll();
  6. print_r($result_arr);
  7. ?>
複製代碼
看上面的代碼,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,具體使用什麼,按照你自己的需要,其他獲取類型參考手冊。

  除了上面這種獲取數據的方式,還有這種:
  1. <?php
  2. $rs = $db->prepare("SELECT * FROM foo");
  3. $rs->execute();
  4. while($row = $rs->fetch()){
  5. print_r($row);
  6. }
  7. ?>
複製代碼
其實差不多啦。如果你想獲取指定記錄裡一個字段結果的話,可以使用 PDOStatement::fetchColumn():
  1. <?php
  2. $rs = $db->query("SELECT COUNT(*) FROM foo");
  3. $col = $rs->fetchColumn();
  4. echo $col;
  5. ?>
複製代碼
一般使用fetchColumn()來進行count統計或者某些只需要單字段的記錄很好操作。

  簡單的總結一下上面的操作:

  查詢操作主要是PDO::query()、PDO::exec()、PDO::prepare()。PDO::query()主要是用於有記錄 結果返回的操作
,特別是SELECT操作,PDO::exec()主要是針對沒有結果集合返回的操作,
比如INSERT、UPDATE、DELETE等操 作,它返回的結果是當前操作影響的列數。

PDO::prepare()主要是預處理操作,需要通過$rs->execute()來執行預處理裡面的SQL 語句,這個方法可以綁定參數,功能比較強大,不是本文能夠簡單說明白的,大家可以參考手冊和其他文檔。
獲取結果集操作主要是:PDOStatement::fetchColumn()、PDOStatement::fetch()、 PDOStatement::fetchALL()。PDOStatement::fetchColumn() 是獲取結果指定第一條記錄的某個字段,缺省是第一個字段。
PDOStatement::fetch() 是用來獲取一條記錄,PDOStatement::fetchAll()是獲取所有記錄集到一個中,獲取結果可以通過PDOStatement:: setFetchMode來設置需要結果集合的類型。

  另外有兩個周邊的操作,一個是PDO::lastInsertId()和PDOStatement::rowCount()。PDO:: lastInsertId()是返回上次插入操作,主鍵列類型是自動新增的最後的流水號ID。

PDOStatement::rowCount()主要是用於 PDO::query()和PDO::prepare()進行DELETE、INSERT、UPDATE操作影響的結果集,對PDO::exec()方法 和SELECT操作無效。



  【錯誤處理】

  如果程序中碰到錯誤咋辦?我們這裡描述PDO類的錯誤信息和異常處理。

  1. 面向對象的方式

  先看看如果連接錯誤等的處理,使用面向對象的方式來處理:
  1. <?php
  2. try {
  3. $db = new PDO(mysql:host=localhost;dbname=test, $user, $pass);
  4. $db = null;
  5. }

  6. catch (PDOException $e)

  7. {
  8. print "Error: " . $e->getMessage() . "<br/>";
  9. die();
  10. }
  11. ?>
複製代碼
這裡利用我們PHP 5面向對象的異常處理特徵,如果裡面有異常的話就初始化調用PDOException來初始化一個異常類。

  PDOException異常類的屬性結構:
  1. <?php
  2. class PDOException extends Exception
  3. {
  4. public $errorInfo = null; // 錯誤信息,可以調用 PDO::errorInfo() 或 PDOStatement::errorInfo()來訪問
  5. protected $message; // 異常信息,可以試用 Exception::getMessage() 來訪問
  6. protected $code; // SQL狀態錯誤代碼,可以使用 Exception::getCode() 來訪問
  7. }
  8. ?>
複製代碼
這個異常處理類是集成PHP 5內置的異常處理類,我們簡單的看一下PHP 5內置的異常處理類結構:
  1. <?php
  2. class Exception
  3. {
  4. // 屬性
  5. protected $message = Unknown exception; // 異常信息
  6. protected $code = 0; // 用戶自定義異常代碼
  7. protected $file; // 發生異常的文件名
  8. protected $line; // 發生異常的代碼行號

  9. // 方法
  10. final function getMessage(); // 返回異常信息
  11. final function getCode(); // 返回異常代碼
  12. final function getFile(); // 返回發生異常的文件名
  13. final function getLine(); // 返回發生異常的代碼行號
  14. final function getTrace(); // backtrace() 數組
  15. final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息
  16. }
  17. ?>
複製代碼
相應的,在代碼中可以合適的調用 getFile() 和 getLine() 來進行錯誤定位,更方便的進行調試。

  2. 使用面向過程的方法

  先看代碼:
  1. <?
  2. $db = new PDO(mysql:host=localhost;dbname=test, $user, $pass);
  3. $rs = $db->query("SELECT aa,bb,cc FROM foo");
  4. if ($db->errorCode() != 00000){
  5. print_r($db->errorInfo());
  6. exit;
  7. }
  8. $arr = $rs->fetchAll();
  9. print_r($arr);
  10. $db = null;
  11. ?>
複製代碼
PDO和PDOStatement對象有errorCode() 和 errorInfo() 方法,如果沒有任何錯誤, errorCode() 返回的是: 00000 ,否則就會返回一些錯誤代碼。errorInfo() 返回的一個數組,包括PHP定義的錯誤代碼和MySQL的錯誤代碼和錯誤信息,數組結構如下:
  1. Array
  2. (
  3. [0] => 42S22
  4. [1] => 1054
  5. [2] => Unknown column aaa in field list
  6. )
複製代碼
每次執行查詢以後,errorCode() 的結果都是最新的,所以我們可以很容易自己控制錯誤信息顯示。



  【簡單總結】

   從上面的使用看出,PDO功能確實強大,另外還有一些內容我沒有講到,比如綁定參數、預處理、存儲過程、事務處理等等功能。另外還有不同數據擴 DSN的構造,Oracle數據庫自己很多特殊的東西,都需要深入去學習理解,這篇文章就只是簡單的描述了一些入門知識,算是對PDO一個簡單的瞭解吧。
2#
發表於 2013-9-18 15:15:00 | 只看該作者
會用 PDO::prepare() 來執行Select查詢其實最大差異是為了防範SQL injection,

就原文範例來實作 PDO::prepare() & PDOStatement::execute:
  1. $username = "myname";
  2. $sql = "SELECT * FROM test WHERE username=?";
  3. $rs = $db->prepare($sql);
  4. $rs->execute(array($username));
  5. while($row = $rs->fetch()){
  6. print_r($row);
  7. }
複製代碼
防範SQL injection,PDO::query是另一種作法,但不建議:(PHP官方)
If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into an SQL statement. Prepared statements with bound parameters are not only more portable, more convenient, immune to SQL injection, but are often much faster to execute than interpolated queries, as both the server and client side can cache a compiled form of the query.
回復 支持 反對

使用道具 舉報

3#
發表於 2013-9-25 14:57:05 | 只看該作者
試了一下print table,文中好像沒有提到細節:

承文中DB連結
  1. while ($row = $rs->fetch(PDO::FETCH_ASSOC))
  2. {
  3. echo $row['ID'];
  4. echo $row['TITLE'];
  5. }
複製代碼
其中ID、TITLE為資料表欄位名稱。
回復 支持 反對

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

本論壇為非營利之網路平台,所有文章內容均為網友自行發表,不代表論壇立場!若涉及侵權、違法等情事,請告知版主處理。


Page Rank Check

廣告刊登  |   交換連結  |   贊助我們  |   服務條款  |   免責聲明  |   客服中心  |   中央分站

手機版|中央論壇

GMT+8, 2026-5-21 15:17 , Processed in 0.042071 second(s), 17 queries .

Powered by Discuz!

© 2005-2015 Copyrights. Set by YIDAS

快速回復 返回頂部 返回列表