- PHP從入門到精通(微視頻精編版)
- 明日科技
- 3811字
- 2020-11-23 14:41:20
第10章 PDO數(shù)據(jù)庫抽象層
(視頻講解:45分鐘)
在PHP的早期版本中,各種不同的數(shù)據(jù)庫擴(kuò)展(MySQL、MS SQL、Oracle)根本沒有真正的一致性,雖然都可以實(shí)現(xiàn)相同的功能,但是這些擴(kuò)展卻互不兼容,都有各自的操作函數(shù),各自為政。結(jié)果導(dǎo)致PHP的維護(hù)非常困難,可移植性也非常差,為了解決這些問題,PHP的開發(fā)人員編寫了一種輕型、便利的API來統(tǒng)一各種數(shù)據(jù)庫的共性,從而達(dá)到PHP腳本最大程度的抽象性和兼容性,這就是數(shù)據(jù)庫抽象層。而在本章中將要介紹的是目前PHP抽象層中最為流行的一種——PDO數(shù)據(jù)庫抽象層。
學(xué)習(xí)摘要:
PDO概述
使用PDO連接數(shù)據(jù)庫
PDO中執(zhí)行SQL語句
PDO中獲取結(jié)果集
捕獲異常
10.1 什么是PDO

視頻講解
10.1.1 PDO概述
PDO是PHP Date Object(PHP數(shù)據(jù)對(duì)象)的簡稱,它是與PHP 5.1版本一起發(fā)行的,目前支持的數(shù)據(jù)庫包括Firebird、FreeTDS、Interbase、MySQL、MS SQL Server、ODBC、Oracle、PostgreSQL、SQLite和Sybase。有了PDO,不必再使用mysql_*函數(shù)、oci_*函數(shù)或者mssql_*函數(shù),也不必再為它們封裝數(shù)據(jù)庫操作類,只需要使用PDO接口中的方法就可以對(duì)數(shù)據(jù)庫進(jìn)行操作。在選擇不同的數(shù)據(jù)庫時(shí),只需修改PDO的DSN(數(shù)據(jù)源名稱)即可。
注意
從PHP 5.1開始附帶了PDO,PDO需要PHP 5核心的新面向?qū)ο筇匦裕虼瞬荒茉谳^早版本的PHP上運(yùn)行。
10.1.2 PDO特點(diǎn)
PDO是一個(gè)“數(shù)據(jù)庫訪問抽象層”,作用是統(tǒng)一各種數(shù)據(jù)庫的訪問接口,與MySQL函數(shù)庫相比,PDO讓跨數(shù)據(jù)庫的使用更具有親和力;與ADODB和MDB2相比,PDO更高效。此外,PDO還具有以下特點(diǎn):
PDO將通過一種輕型、清晰、方便的函數(shù),統(tǒng)一各種不同RDBMS庫的共有特性,實(shí)現(xiàn)PHP腳本最大程度的抽象性和兼容性。
PDO吸取現(xiàn)有數(shù)據(jù)庫擴(kuò)展成功和失敗的經(jīng)驗(yàn)教訓(xùn),利用PHP 5的最新特性,可以輕松地與各種數(shù)據(jù)庫進(jìn)行交互。
PDO擴(kuò)展是模塊化的,能夠在運(yùn)行時(shí)為數(shù)據(jù)庫后端加載驅(qū)動(dòng)程序,而不必重新編譯或重新安裝整個(gè)PHP程序。例如,PDO_MySQL擴(kuò)展會(huì)替代PDO擴(kuò)展,實(shí)現(xiàn)MySQL數(shù)據(jù)庫API。還有一些用于Oracle、PostgreSQL、ODBC和Firebird的驅(qū)動(dòng)程序。
10.1.3 安裝PDO
默認(rèn)情況下,PDO在PHP 7中為開啟狀態(tài),但是要啟用對(duì)某個(gè)數(shù)據(jù)庫驅(qū)動(dòng)程序的支持,仍需要進(jìn)行相應(yīng)的配置操作。
在Windows環(huán)境下,PDO在php.ini文件中進(jìn)行配置,如圖10.1所示。

圖10.1 Windows環(huán)境下配置PDO
要啟用PDO,首先必須加載extension=php_pdo.dll,如果要想其支持某個(gè)具體的數(shù)據(jù)庫,那么還要加載對(duì)應(yīng)的數(shù)據(jù)庫選項(xiàng)。例如,要支持MySQL數(shù)據(jù)庫,則需要加載extension=php_pdo_mysql.dll選項(xiàng)。
注意
在完成數(shù)據(jù)庫的加載后,要保存php.ini文件,并且重新啟動(dòng)Apache服務(wù)器,修改才能夠生效。
10.2 PDO連接數(shù)據(jù)庫

視頻講解
10.2.1 PDO構(gòu)造函數(shù)
在PDO中,要建立與數(shù)據(jù)庫的連接需要實(shí)例化PDO的構(gòu)造函數(shù),PDO構(gòu)造函數(shù)的語法格式如下:

參數(shù)說明如下。
dsn:數(shù)據(jù)源名,包括主機(jī)名、端口號(hào)和數(shù)據(jù)庫名稱。
username:連接數(shù)據(jù)庫的用戶名。
password:連接數(shù)據(jù)庫的密碼。
driver_options:連接數(shù)據(jù)庫的其他選項(xiàng)。
通過PDO連接MySQL數(shù)據(jù)庫的代碼如下:

10.2.2 DSN詳解
DSN是Data Source Name(數(shù)據(jù)源名稱)的首字母縮寫。DSN提供連接數(shù)據(jù)庫需要的信息。PDO的DSN包括3部分:PDO驅(qū)動(dòng)名稱(如mysql、sqlite或者pgsql)、冒號(hào)和驅(qū)動(dòng)特定的語法。每種數(shù)據(jù)庫都有其特定的驅(qū)動(dòng)語法。
數(shù)據(jù)庫服務(wù)器是完全獨(dú)立于PHP的實(shí)體。數(shù)據(jù)庫服務(wù)器可能與Web服務(wù)器不是在同一臺(tái)計(jì)算機(jī)上,此時(shí)要通過PDO連接數(shù)據(jù)庫時(shí),就需要修改DSN中的主機(jī)名稱。
每種數(shù)據(jù)庫服務(wù)器都有一個(gè)默認(rèn)的端口號(hào)(MySQL默認(rèn)是3306),數(shù)據(jù)庫管理員可以對(duì)端口號(hào)進(jìn)行修改,因此有可能PHP找不到數(shù)據(jù)庫的端口,此時(shí)就需要在DSN中包含端口號(hào)。
另外由于一個(gè)數(shù)據(jù)庫服務(wù)器中可能擁有多個(gè)數(shù)據(jù)庫,所以在通過DSN連接數(shù)據(jù)庫時(shí),通常都包括數(shù)據(jù)庫名稱,這樣可以確保連接的是想要的數(shù)據(jù)庫,而不是其他的數(shù)據(jù)庫。
10.3 PDO中執(zhí)行SQL語句

視頻講解
在PDO中,可以使用下面的3種方法來執(zhí)行SQL語句。
1.exec()方法
exec()方法返回執(zhí)行后受影響的行數(shù),其語法格式如下:

參數(shù)$statement是要執(zhí)行的SQL語句。該方法返回執(zhí)行查詢時(shí)受影響的行數(shù),通常用于insert、delete和update語句中。
例如,使用exec()執(zhí)行刪除操作,刪除member表中id為1的記錄。代碼如下:

2.query()方法
query()方法用于返回執(zhí)行查詢后的結(jié)果集。其語法格式如下:

其中參數(shù)$statement是要執(zhí)行的SQL語句。它返回的是一個(gè)PDOStatement對(duì)象。
例如,使用query()執(zhí)行查詢操作,查詢member表中所有記錄的id。代碼如下:

3.預(yù)處理語句——prepare()和execute()
預(yù)處理語句包括prepare()和execute()兩個(gè)方法。首先,通過prepare()方法做查詢的準(zhǔn)備工作,語法格式如下:

其中參數(shù)$statement是要執(zhí)行的SQL語句。它返回的是一個(gè)PDOStatement對(duì)象。
然后,通過execute()方法執(zhí)行查詢,并且還可以通過bindParam()方法來綁定參數(shù)提供給execute()方法。其語法格式如下:

例如,查詢member表中id大于2且會(huì)員等級(jí)為C的所有記錄。代碼如下:

10.4 PDO中獲取結(jié)果集

視頻講解
在PDO中獲取結(jié)果集常用3種方法:fetch()、fetchAll()和fetchColumn()。
10.4.1 fetch()方法
fetch()方法可以獲取結(jié)果集中的下一行記錄,其語法格式如下:

參數(shù)說明如下。
fetch_style:控制結(jié)果集的返回方式,其可選方式如表10.1所示。
表10.1 fetch_style控制結(jié)果集的可選值

cursor_orientation:PDOStatement對(duì)象的一個(gè)滾動(dòng)游標(biāo),可用于獲取指定的一行。
cursor_offset:游標(biāo)的偏移量。
【例10.01】 使用fetch()方法獲取明日學(xué)院會(huì)員列表。(實(shí)例位置:資源包\源碼\10\10.01)
通過fetch()方法獲取結(jié)果集中下一行的數(shù)據(jù),進(jìn)而應(yīng)用while語句完成數(shù)據(jù)庫中數(shù)據(jù)的循環(huán)輸出,具體步驟如下。
(1)創(chuàng)建member表。首先創(chuàng)建database10數(shù)據(jù)庫,并設(shè)置數(shù)據(jù)庫編碼格式為UTF-8。創(chuàng)建member表的SQL語句如下:

(2)插入測(cè)試數(shù)據(jù)。為了顯示會(huì)員信息,我們需要先在member表中插入幾條測(cè)試數(shù)據(jù)。插入數(shù)據(jù)的SQL語句如下:

(3)創(chuàng)建數(shù)據(jù)庫配置文件config.php,代碼如下:

(4)創(chuàng)建index.php文件,用于連接數(shù)據(jù)庫,執(zhí)行查詢語句,并引入模板文件。index.php文件的具體代碼如下:

(5)創(chuàng)建lists.html文件,顯示會(huì)員信息。使用$result->fetch(PDO::FETCH_ASSOC)將結(jié)果集返回到數(shù)組中,通過while語句循環(huán)遍歷數(shù)組,將各會(huì)員的數(shù)據(jù)插入到<table>表格中,具體代碼如下:

使用瀏覽器訪問index.php,運(yùn)行結(jié)果如圖10.2所示。

圖10.2 顯示會(huì)員列表
10.4.2 fetchAll()方法
fetchAll()方法可以獲取結(jié)果集中的所有行。其語法格式如下:

參數(shù)及返回值說明如下。
fetch_style:控制結(jié)果集中數(shù)據(jù)的顯示方式。
column_index:字段的索引。
返回值:是一個(gè)包含結(jié)果集中所有數(shù)據(jù)的二維數(shù)組。
【例10.02】 使用fetchAll()方法獲取明日學(xué)院會(huì)員列表。(實(shí)例位置:資源包\源碼\10\10.02)
通過fetchAll()方法獲取結(jié)果集中所有行,并且通過foreach語句讀取二維數(shù)組中的數(shù)據(jù),完成數(shù)據(jù)庫中數(shù)據(jù)的循環(huán)輸出。由于開發(fā)流程與例10.01相似,這里只介紹修改的關(guān)鍵代碼。
(1)創(chuàng)建index.php文件,用于連接數(shù)據(jù)庫,執(zhí)行查詢語句,并引入模板文件。使用fetchAll(PDO::FETCH_ASSOC)方法獲取結(jié)果集中所有行,將結(jié)果賦值給$data數(shù)組。index.php文件修改后代碼如下:

(2)創(chuàng)建lists.html文件。使用foreach語句遍歷$data數(shù)組,將相應(yīng)數(shù)據(jù)寫入<table>表格,關(guān)鍵代碼如下:

運(yùn)行結(jié)果與例10.01相同。
10.4.3 fetchColumn()方法
fetchColumn()方法可以獲取結(jié)果集中下一行指定列的值。其語法格式如下:

其中可選參數(shù)column_number設(shè)置行中列的索引值,該值從0開始。如果省略該參數(shù)則從第1列開始取值。
【例10.03】 使用fetchColumn()方法讀取會(huì)員名。(實(shí)例位置:資源包\源碼\10\10.03)
通過fetchColumn()方法獲取結(jié)果集中下一行中指定列的值,注意這里是“指定列的值”。本實(shí)例輸出member表中nickname的值。具體步驟如下。
(1)創(chuàng)建index.php文件,用于連接數(shù)據(jù)庫,執(zhí)行查詢語句,并引入模板文件。index.php文件的具體代碼如下:

(2)創(chuàng)建lists.html文件,使用fetchColumn()方法獲取nickname。關(guān)鍵代碼如下:

運(yùn)行結(jié)果如圖10.3所示。

圖10.3 fetchColumn()方法獲取用戶昵稱
10.5 PDO中捕獲SQL語句中的錯(cuò)誤

視頻講解
在PDO中有3種方法可以捕獲SQL語句中的錯(cuò)誤,分別為:默認(rèn)模式(PDO::ERRMODE_SILENT)、警告模式(PDO::ERRMODE_WARNING)和異常模式(PDO::ERRMODE_EXCEPTION)。下面就對(duì)這3種方法分別進(jìn)行講解。
10.5.1 默認(rèn)模式
在默認(rèn)模式中設(shè)置PDOStatement對(duì)象的errorCode屬性,但不進(jìn)行其他任何操作。
通過prepare()和execute()方法向數(shù)據(jù)庫中添加數(shù)據(jù),設(shè)置PDOStatement對(duì)象的errorCode屬性,手動(dòng)檢測(cè)代碼中的錯(cuò)誤。
【例10.04】 使用默認(rèn)模式捕獲SQL語句中的錯(cuò)誤。(實(shí)例位置:資源包\源碼\10\10.04)
創(chuàng)建index.php文件。通過PDO連接MySQL數(shù)據(jù)庫,通過預(yù)處理語句prepare()和execute()執(zhí)行insert添加語句,向數(shù)據(jù)表中添加數(shù)據(jù),并且設(shè)置PDOStatement對(duì)象的errorCode屬性,檢測(cè)代碼中的錯(cuò)誤。代碼如下:

在本實(shí)例中,在定義insert添加語句時(shí),使用了錯(cuò)誤的數(shù)據(jù)表名稱members(正確名稱是member),導(dǎo)致輸出結(jié)果如圖10.4所示。

圖10.4 在默認(rèn)模式中捕獲SQL中的錯(cuò)誤
10.5.2 警告模式
警告模式會(huì)產(chǎn)生一個(gè)PHP警告,并設(shè)置errorCode屬性。如果設(shè)置的是警告模式,那么除非明確地檢查錯(cuò)誤代碼,否則程序?qū)⒗^續(xù)按照其方式運(yùn)行。
例如,設(shè)置警告模式,通過prepare()和execute()方法讀取數(shù)據(jù)庫中數(shù)據(jù),體會(huì)在設(shè)置成警告模式后執(zhí)行錯(cuò)誤的SQL語句。具體代碼如下:

在設(shè)置為警告模式后,如果SQL語句出現(xiàn)錯(cuò)誤將給出一個(gè)提示信息,但是程序仍能夠繼續(xù)執(zhí)行下去,其運(yùn)行結(jié)果如圖10.5所示。

圖10.5 設(shè)置警告模式后捕獲的SQL語句錯(cuò)誤
10.5.3 異常模式
異常模式會(huì)創(chuàng)建一個(gè)PDOException,并設(shè)置errorCode屬性。它可以將執(zhí)行代碼封裝到一個(gè)try{…}catch{…}語句塊中。未捕獲的異常將會(huì)導(dǎo)致腳本中斷,并顯示堆棧跟蹤,讓我們了解是哪里出現(xiàn)的問題。
例如,在執(zhí)行數(shù)據(jù)庫中數(shù)據(jù)的刪除操作時(shí),設(shè)置為異常模式,并且編寫一個(gè)錯(cuò)誤的SQL語句(操作錯(cuò)誤的數(shù)據(jù)表members),體會(huì)異常模式與警告模式和默認(rèn)模式的區(qū)別。具體代碼如下:

在設(shè)置為異常模式后,執(zhí)行錯(cuò)誤的SQL語句返回的結(jié)果如圖10.6所示。

圖10.6 異常模式捕獲的SQL語句錯(cuò)誤信息
10.6 小結(jié)
本章重點(diǎn)介紹了數(shù)據(jù)庫抽象層——PDO,從它的概述、特點(diǎn)和安裝開始講解,到它的實(shí)際應(yīng)用,包括如何連接不同的數(shù)據(jù)庫、如何執(zhí)行SQL語句、如何獲取結(jié)果集,以及錯(cuò)誤處理,再到它的高級(jí)應(yīng)用事務(wù)都進(jìn)行了詳細(xì)講解,并且都配有相應(yīng)的實(shí)例。通過本章的學(xué)習(xí),相信讀者能夠掌握PDO技術(shù)的應(yīng)用。
10.7 實(shí)戰(zhàn)
10.7.1 獲取所有會(huì)員的“郵箱”信息
實(shí)例位置:資源包\源碼\10\實(shí)戰(zhàn)\01
試著修改例10.03,使用fetchColumn()方法獲取所有會(huì)員的“郵箱”信息。
10.7.2 使用默認(rèn)模式捕獲SQL語句中的錯(cuò)誤
實(shí)例位置:資源包\源碼\10\實(shí)戰(zhàn)\02
試著刪除例10.04中config.php文件中的數(shù)據(jù)庫密碼,使用默認(rèn)模式捕獲SQL語句中的錯(cuò)誤,如圖10.7所示。

圖10.7 捕獲異常
- 深入核心的敏捷開發(fā):ThoughtWorks五大關(guān)鍵實(shí)踐
- 程序員修煉之道:程序設(shè)計(jì)入門30講
- Beginning C++ Game Programming
- C語言程序設(shè)計(jì)(第2 版)
- Photoshop智能手機(jī)APP UI設(shè)計(jì)之道
- C#完全自學(xué)教程
- Mastering Julia
- React.js Essentials
- Getting Started with SQL Server 2012 Cube Development
- 可解釋機(jī)器學(xué)習(xí):模型、方法與實(shí)踐
- RISC-V體系結(jié)構(gòu)編程與實(shí)踐(第2版)
- 劍指大數(shù)據(jù):企業(yè)級(jí)數(shù)據(jù)倉庫項(xiàng)目實(shí)戰(zhàn)(在線教育版)
- Advanced Express Web Application Development
- 持續(xù)輕量級(jí)Java EE開發(fā):編寫可測(cè)試的代碼
- Domain-Driven Design in PHP