PHP網(wǎng)站開發(fā)實(shí)例教程(第3版) 課件 第8、9章 PHP框架基礎(chǔ)(下)、PDO擴(kuò)展和Smarty模板引擎_第1頁(yè)
PHP網(wǎng)站開發(fā)實(shí)例教程(第3版) 課件 第8、9章 PHP框架基礎(chǔ)(下)、PDO擴(kuò)展和Smarty模板引擎_第2頁(yè)
PHP網(wǎng)站開發(fā)實(shí)例教程(第3版) 課件 第8、9章 PHP框架基礎(chǔ)(下)、PDO擴(kuò)展和Smarty模板引擎_第3頁(yè)
PHP網(wǎng)站開發(fā)實(shí)例教程(第3版) 課件 第8、9章 PHP框架基礎(chǔ)(下)、PDO擴(kuò)展和Smarty模板引擎_第4頁(yè)
PHP網(wǎng)站開發(fā)實(shí)例教程(第3版) 課件 第8、9章 PHP框架基礎(chǔ)(下)、PDO擴(kuò)展和Smarty模板引擎_第5頁(yè)
已閱讀5頁(yè),還剩153頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第8章PHP框架基礎(chǔ)(下)《PHP網(wǎng)站開發(fā)實(shí)例教程(第3版)》學(xué)習(xí)目標(biāo)/Target

掌握Composer的使用,能夠使用Composer管理項(xiàng)目。

掌握框架基礎(chǔ)搭建,能夠?qū)崿F(xiàn)App類、Request類、Response類和Container類。

掌握反射API的使用方法,能夠使用反射API實(shí)現(xiàn)反射。

掌握依賴注入的使用方法,能夠利用反射實(shí)現(xiàn)依賴注入。

熟悉框架的目錄結(jié)構(gòu),能夠說出每個(gè)目錄的作用。學(xué)習(xí)目標(biāo)/Target

掌握異常的拋出和捕獲,能夠在程序中拋出和捕獲異常。

掌握自定義異常類的實(shí)現(xiàn),能夠根據(jù)需求實(shí)現(xiàn)自定義異常類。

掌握多異常捕獲處理,能夠在程序中實(shí)現(xiàn)多異常的捕獲處理。

掌握異常嵌套的實(shí)現(xiàn),能夠在程序中使用異常嵌套。章節(jié)概述/Summary學(xué)習(xí)了第7章的框架基礎(chǔ)知識(shí)后,相信讀者已經(jīng)可以在自定義框架中實(shí)現(xiàn)指定的功能。為了讓讀者對(duì)框架有更深入的理解,本章將對(duì)框架的底層設(shè)計(jì)思想和實(shí)現(xiàn)原理進(jìn)行講解,內(nèi)容包括劃分框架目錄結(jié)構(gòu)、使用Composer管理項(xiàng)目、框架基礎(chǔ)搭建、反射和異常處理。目錄/Contents8.18.28.3劃分框架目錄結(jié)構(gòu)使用Composer管理項(xiàng)目框架基礎(chǔ)搭建8.4反射8.5異常處理劃分框架目錄結(jié)構(gòu)8.1

先定一個(gè)小目標(biāo)!熟悉框架的目錄結(jié)構(gòu),能夠說出每個(gè)目錄的作用。8.1劃分框架目錄結(jié)構(gòu)通常情況下,一個(gè)項(xiàng)目由許多不同類型的文件組成,為了更好地管理這些文件,需要?jiǎng)澐帜夸浗Y(jié)構(gòu)。為了讓自定義框架的目錄結(jié)構(gòu)更接近常用的PHP框架,本書參考Laravel框架的目錄結(jié)構(gòu),對(duì)自定義框架進(jìn)行目錄劃分,將自定義框架命名為myframe.test。8.1劃分框架目錄結(jié)構(gòu)myframe.test框架的目錄結(jié)構(gòu):├─app 框架核心目錄│├─Http HTTP請(qǐng)求目錄││├─Controllers 控制器目錄│├─Models 模型目錄├─resources 資源目錄│├─views 視圖目錄├─public 公開目錄├─myframe 框架目錄├─vendor Composer依賴包目錄(由Composer自動(dòng)創(chuàng)建)8.1劃分框架目錄結(jié)構(gòu)使用Composer管理項(xiàng)目8.2

先定一個(gè)小目標(biāo)!掌握Composer的安裝,能夠獨(dú)立安裝Composer。8.2.1安裝ComposerComposer是PHP項(xiàng)目中管理項(xiàng)目依賴的工具,開發(fā)人員在項(xiàng)目中聲明依賴的外部工具庫(kù),Composer就會(huì)自動(dòng)安裝工具庫(kù)依賴的庫(kù)文件。大多數(shù)PHP框架都支持Composer。在Composer官方網(wǎng)站可以下載Composer。在Windows中安裝Composer的方式有兩種:使用安裝程序安裝使用命令行安裝8.2.1安裝Composer1在Composer官網(wǎng)下載Composer-Setup.exe,雙擊下載文件啟動(dòng)安裝程序,選擇推薦的安裝模式。安裝程序提示選擇是否使用開發(fā)者模式,若選中此項(xiàng)不提供卸載功能,推薦不選中。2安裝過程提示選擇PHP命令行程序時(shí),單擊“Browse…”按鈕瀏覽文件,選擇C:\web\php8.2\php.exe。38.2.1安裝Composer使用安裝程序安裝的步驟:4進(jìn)入填寫代理服務(wù)器界面,選擇不使用代理,單擊“Next”按鈕。進(jìn)入準(zhǔn)備安裝界面,單擊“Install”按鈕進(jìn)行安裝。5打開新的命令提示符窗口,執(zhí)行“composer”命令測(cè)試Composer是否安裝成功。68.2.1安裝Composer使用安裝程序安裝的步驟:

先定一個(gè)小目標(biāo)!掌握使用Composer實(shí)現(xiàn)自動(dòng)加載的方法,能夠在自定義框架中實(shí)現(xiàn)類的自動(dòng)加載。8.2.2使用Composer實(shí)現(xiàn)自動(dòng)加載雖然PHP提供了自動(dòng)加載機(jī)制,但是要在項(xiàng)目中實(shí)現(xiàn)自動(dòng)加載功能還需要手動(dòng)編寫代碼,操作起來相對(duì)復(fù)雜。為了使開發(fā)更簡(jiǎn)單,可以在myframe.test項(xiàng)目中使用Composer實(shí)現(xiàn)類的自動(dòng)加載。8.2.2使用Composer實(shí)現(xiàn)自動(dòng)加載1在C:\web\www\myframe目錄下創(chuàng)建composer.json文件,定義自動(dòng)加載的命名空間。在命令提示符窗口中切換到composer.json文件所在目錄,執(zhí)行composerinstall命令安裝依賴關(guān)系所需組件,初始化自動(dòng)加載信息。2重新編寫public\index.php文件,引入vendor\autoload.php文件實(shí)現(xiàn)自動(dòng)加載。3在myframe.test項(xiàng)目中使用Composer實(shí)現(xiàn)類的自動(dòng)加載具體步驟:8.2.2使用Composer實(shí)現(xiàn)自動(dòng)加載4將原有的app\StudentController.php放入app\Http\Controllers目錄。將原有的視圖文件views\student.php移動(dòng)到resources\views目錄中。修改public\index.php文件,定義路由規(guī)則,根據(jù)路由找到對(duì)應(yīng)的控制器名和方法名。56在myframe.test項(xiàng)目中使用Composer實(shí)現(xiàn)類的自動(dòng)加載具體步驟:將原有的app\StudentModel.php修改為app\Models\Student.php。修改Student.php,將命名空間放在App下。8.2.2使用Composer實(shí)現(xiàn)自動(dòng)加載

先定一個(gè)小目標(biāo)!掌握使用Composer管理項(xiàng)目依賴的方法,能夠使用Composer安裝和卸載依賴包。8.2.3使用Composer管理項(xiàng)目依賴8.2.3使用Composer管理項(xiàng)目依賴在以前開發(fā)中,如果項(xiàng)目中使用了某個(gè)類庫(kù),需要手動(dòng)下載這個(gè)類庫(kù)的文件,并在代碼中引入類庫(kù)后才能使用。這種方式不僅麻煩,而且當(dāng)類庫(kù)的版本更新后,還需要重新下載類庫(kù)。如果一個(gè)類庫(kù)又依賴于另一個(gè)類庫(kù),這種層疊的依賴關(guān)系會(huì)讓項(xiàng)目的維護(hù)變得復(fù)雜并且低效。為了解決手動(dòng)下載類庫(kù)這個(gè)問題,Composer提供了項(xiàng)目依賴管理功能,它可以自動(dòng)完成依賴包的下載和安裝,并通過命名空間自動(dòng)引入。8.2.3使用Composer管理項(xiàng)目依賴Composer通過packagist資源庫(kù)獲取依賴包。在packagist資源庫(kù)中,依賴包的命名方式為“用戶名/包名”。例如“naux/auto-correct”包能夠在中文和英文之間添加空格,并糾正專用名詞的大小寫。安裝依賴包的兩種方式使用composerrequire命令安裝在配置文件中添加依賴包在composer.json文件中添加包的相關(guān)信息,在命令提示符窗口中執(zhí)行composerinstall命令或執(zhí)行composerupdate命令8.2.3使用Composer管理項(xiàng)目依賴通常情況下,一個(gè)包會(huì)有多個(gè)版本,指定版本號(hào)的多種方式:名稱實(shí)例描述特定的版本3.1.33包的版本是3.1.33某個(gè)范圍的版本~1.0包的版本大于等于1.0且小于1.1^1.0包的版本大于等于1.0且小于2.0>=3.1包的版本大于等于3.1>=2.6,<3.0包的版本大于等于2.6且小于3.0>=2.6,<3.0|>=3.1包的版本大于等于2.6且小于3.0,或大于等于3.1通配符方式3.1.*與>=3.1,<3.2等價(jià)8.2.3使用Composer管理項(xiàng)目依賴以naux/auto-correct包為例,演示使用Composer管理項(xiàng)目依賴:1安裝依賴包需要開啟zip擴(kuò)展,在PHP配置文件php.ini開啟zip擴(kuò)展。在命令提示符窗口中切換到C:\web\www\myframe目錄,執(zhí)行composerrequire命令安裝依賴包。2在app\Http\Controllers\StudentController.php中導(dǎo)入命名空間,編寫test()方法。38.2.3使用Composer管理項(xiàng)目依賴test()方法的代碼:第1種方式publicfunctiontest(){$correct=newAutoCorrect;//在中文和英文之間添加空格

echo$correct->auto_space('《php網(wǎng)站開發(fā)實(shí)例教程》');//糾正專用詞匯的大小寫

echo$correct->auto_correct('《php網(wǎng)站開發(fā)實(shí)例教程》');}輸出結(jié)果:《php網(wǎng)站開發(fā)實(shí)例教程》《PHP網(wǎng)站開發(fā)實(shí)例教程》8.2.3使用Composer管理項(xiàng)目依賴如果想要卸載依賴包,可以使用如下命令:第1種方式composerremovenaux/auto-correct卸載依賴包會(huì)將依賴配置刪除,并刪除vendor目錄中依賴包的相關(guān)文件。8.2.3使用Composer管理項(xiàng)目依賴

先定一個(gè)小目標(biāo)!掌握使用Composer管理項(xiàng)目的方法,能夠創(chuàng)建自己的包。8.2.4【案例】創(chuàng)建自己的包在進(jìn)行項(xiàng)目開發(fā)時(shí),除了可以使用Composer下載packagist中的依賴包外,還可以將自己實(shí)現(xiàn)的功能或項(xiàng)目打包成依賴包,完成測(cè)試后,將其發(fā)布到Packagist資源庫(kù)中供其他人使用。下面通過案例演示如何使用Composer創(chuàng)建自己的包。

案例需求8.2.4【案例】創(chuàng)建自己的包①在C:\web\apache2.4\htdocs目錄中創(chuàng)建包的基礎(chǔ)目錄custom-php-json,在該目錄下創(chuàng)建src目錄和src\Json.php文件,實(shí)現(xiàn)對(duì)數(shù)據(jù)的JSON編碼和解碼。②創(chuàng)建custom-php-json\composer.json文件,編寫包的初始化信息。③在項(xiàng)目中使用創(chuàng)建的包,測(cè)試對(duì)數(shù)據(jù)的JSON編碼和解碼。

實(shí)現(xiàn)思路8.2.4【案例】創(chuàng)建自己的包框架基礎(chǔ)搭建8.3

先定一個(gè)小目標(biāo)!掌握框架基礎(chǔ)搭建,能夠?qū)崿F(xiàn)App類。8.3.1App類App類的代碼用于實(shí)現(xiàn)框架的啟動(dòng)。在前面的開發(fā)中,框架的啟動(dòng)是通過入口文件實(shí)現(xiàn)的,而將啟動(dòng)框架的核心代碼放在App類中,可以使代碼更加符合面向?qū)ο蟮乃枷搿?.3.1App類實(shí)現(xiàn)App類的具體步驟:1準(zhǔn)備工作在composer.json中添加命名空間配置,編寫run()方法實(shí)現(xiàn)應(yīng)用啟動(dòng),在index.php中實(shí)例化App類并調(diào)用run()方法。路由檢測(cè)根據(jù)用戶請(qǐng)求的URL,檢測(cè)對(duì)應(yīng)的控制器名和方法名。例如,用戶請(qǐng)求的URL:http://www.myframe.test/student/test,檢測(cè)結(jié)果為Student控制器test()方法。2請(qǐng)求分發(fā)在App類中,根據(jù)路由檢測(cè)的結(jié)果調(diào)用對(duì)應(yīng)控制器和方法,實(shí)現(xiàn)請(qǐng)求分發(fā)。38.3.1App類

先定一個(gè)小目標(biāo)!掌握框架基礎(chǔ)搭建,能夠?qū)崿F(xiàn)Request類。8.3.2Request類Request類負(fù)責(zé)獲取請(qǐng)求信息,它是對(duì)當(dāng)前請(qǐng)求的封裝。通過Request類可以獲取$_GET、$_POST、$_SERVER等超全局變量中的數(shù)據(jù)。與直接訪問超全局變量相比,使用Request類可以對(duì)所有的請(qǐng)求數(shù)據(jù)進(jìn)行統(tǒng)一處理,提供一種面向?qū)ο蟆⒑?jiǎn)單易用的操作方式。下面以獲取$_SERVER超全局變量的請(qǐng)求信息為例進(jìn)行講解。8.3.2Request類實(shí)現(xiàn)Request類的具體步驟:1創(chuàng)建myframe\Request.php文件編寫server()方法和pathinfo()方法,其中server()方法用于獲取$_SERVER中的數(shù)據(jù),pathinfo()方法用于解析PATH_INFO。在App類中使用Request類在App類中定義構(gòu)造方法實(shí)例化Request類,修改routeCheck()方法,調(diào)用Request類的pathinfo()方法獲取請(qǐng)求信息。28.3.2Request類

先定一個(gè)小目標(biāo)!掌握框架基礎(chǔ)搭建,能夠?qū)崿F(xiàn)Response類。8.3.3Response類Response類負(fù)責(zé)處理響應(yīng)信息。將響應(yīng)輸出的代碼封裝到Response類中,開發(fā)人員不再需要使用其他輸出語(yǔ)句輸出數(shù)據(jù),輸出數(shù)據(jù)的工作由Response類處理。下面講解如何實(shí)現(xiàn)Response類。8.3.3Response類實(shí)現(xiàn)Response類的具體步驟:1創(chuàng)建myframe\Response.php文件在類中定義$code、$header和$data屬性,分別表示響應(yīng)狀態(tài)碼、響應(yīng)頭和響應(yīng)數(shù)據(jù)。實(shí)現(xiàn)Response類編寫構(gòu)造方法,在創(chuàng)建對(duì)象時(shí)傳入基本參數(shù),編寫send()方法用于輸出數(shù)據(jù),編寫create()靜態(tài)方法用于創(chuàng)建本類對(duì)象。2使用Response類在App類的dispatch()方法中,接收控制器的返回結(jié)果并創(chuàng)建Response實(shí)例,在App類的run()方法中返回Response實(shí)例,在public\index.php中,修改啟動(dòng)應(yīng)用的代碼,調(diào)用send()方法將結(jié)果輸出。38.3.3Response類

先定一個(gè)小目標(biāo)!掌握框架基礎(chǔ)搭建,能夠?qū)崿F(xiàn)Container類。8.3.4Container類在框架中,有許多類只希望被實(shí)例化一次,例如,數(shù)據(jù)庫(kù)操作類。為了避免一個(gè)類被重復(fù)實(shí)例化,通常將這些類的對(duì)象放到容器中。Container類表示容器,它用于創(chuàng)建對(duì)象,并將創(chuàng)建的對(duì)象放在容器中,當(dāng)再次創(chuàng)建相同類的對(duì)象時(shí),如果容器中存在則直接返回,不必重復(fù)創(chuàng)建。下面講解如何實(shí)現(xiàn)Container類。8.3.4Container類實(shí)現(xiàn)Container類的具體步驟:1創(chuàng)建myframe\Container.php文件創(chuàng)建make()方法用于創(chuàng)建對(duì)象,將對(duì)象保存在數(shù)組中,定義靜態(tài)方法getInstance()創(chuàng)建自身對(duì)象,修改App類的構(gòu)造方法,通過Container::getInstance()創(chuàng)建容器對(duì)象。使用Container類修改App類繼承Container類,在構(gòu)造方法中創(chuàng)建Request對(duì)象。28.3.4Container類反射8.4

先定一個(gè)小目標(biāo)!掌握反射API的使用,能夠使用反射API實(shí)現(xiàn)反射。8.4.1反射API反射是PHP針對(duì)面向?qū)ο缶幊烫峁┑囊环N“自省”的過程??梢詫⑵淅斫鉃楦鶕?jù)“目的地”尋找“出發(fā)地或來源”。例如,對(duì)某個(gè)對(duì)象進(jìn)行反射,找到這個(gè)對(duì)象所屬的類、擁有的方法和屬性、方法的參數(shù)、文檔注釋等詳細(xì)信息。8.4.1反射API在PHP中使用反射,主要通過反射API來完成。反射API常用的類與接口:8.4.1反射API類/接口說明Reflection反射類Reflector反射接口ReflectionClass獲取類的相關(guān)信息ReflectionObject獲取對(duì)象的相關(guān)信息ReflectionMethod獲取方法的相關(guān)信息ReflectionProperty獲取類的屬性的相關(guān)信息ReflectionParameter獲取函數(shù)或方法參數(shù)的相關(guān)信息1/2在PHP中使用反射,主要通過反射API來完成。反射API常用的類與接口:8.4.1反射API類/接口實(shí)例ReflectionExtension獲取擴(kuò)展的相關(guān)信息ReflectionFunction獲取函數(shù)的相關(guān)信息ReflectionFunctionAbstractReflectionFunction的父類ReflectionException用于反射異常處理ReflectionClassConstant獲取類常量的信息ReflectionType獲取參數(shù)或者返回值的類型2/2ReflectionClass類常用的方法:8.4.1反射API類名方法名功能描述ReflectionClassgetMethod()獲取一個(gè)類方法的ReflectionMethod對(duì)象getName()獲取類名getConstructor()獲取類的構(gòu)造函數(shù)getProperties()獲取一組屬性hasMethod()檢查方法是否已定義hasProperty()檢查屬性是否已定義newInstance()通過指定的參數(shù)創(chuàng)建一個(gè)新的類實(shí)例newInstanceArgs()通過數(shù)組參數(shù)創(chuàng)建一個(gè)新的類實(shí)例ReflectionMethod類和ReflectionFunctionAbstract類常用的方法:8.4.1反射API類名方法名功能描述ReflectionMethodinvoke()實(shí)現(xiàn)執(zhí)行操作invokeArgs()帶參數(shù)執(zhí)行isPublic()判斷方法是不是公開方法ReflectionFunctionAbstractgetNumberOfParameters()獲取參數(shù)數(shù)目getParameters獲取參數(shù)ReflectionProperty類常用的方法:8.4.1反射API類名方法名功能描述ReflectionPropertygetDocComment()獲取屬性文檔注釋getName()獲取屬性名稱getValue()獲取屬性值isDefault()檢查屬性是不是默認(rèn)屬性isPrivate()檢查屬性是不是私有屬性isProtected()檢查屬性是不是保護(hù)屬性isPublic()檢查屬性是不是公有屬性isStatic()檢查屬性是不是靜態(tài)屬性ReflectionParameter類和ReflectionExtension類常用的方法:8.4.1反射API類名方法名功能描述ReflectionParametergetClass()獲得類型提示類getDefaultValue()獲取默認(rèn)屬性值ReflectionExtensiongetFunctions()獲取擴(kuò)展中的函數(shù)getINIEntries()獲取ini配置getVersion()獲取擴(kuò)展版本號(hào)info()輸出擴(kuò)展信息8.4.1反射API下面演示如何使用反射獲取類屬性的信息,具體步驟如下。<?php//定義一個(gè)類,用于測(cè)試classUpload{/***上傳文件信息*/private$file=[];/***上傳文件保存目錄*/public$upload_dir='/upload/';}8.4.1反射APISTEP01編寫Upload.php文件。該文件用于后續(xù)通過反射來獲取其基本信息。<?phprequire'./upload.php';//獲取類中所有的屬性$reflect=newReflectionClass('Upload');$properties=$reflect->getProperties();var_dump($properties);foreach($propertiesas$property){if($property->isPublic()){var_dump($property->getDocComment()); //文檔注釋

var_dump($property->getName()); //屬性名稱

var_dump($property->getValue(newUpload)); //屬性值

}}8.4.1反射APISTEP02創(chuàng)建reflect.php文件。引入U(xiǎn)pload.php,獲取Upload類的所有屬性,輸出其中的公有屬性。獲取Upload類的反射對(duì)象,通過反射對(duì)象調(diào)用getProperties()方法獲取Upload類的所有屬性8.4.1反射APISTEP03reflect.php文件的運(yùn)行結(jié)果。

先定一個(gè)小目標(biāo)!掌握依賴注入的使用,能夠利用反射實(shí)現(xiàn)依賴注入。8.4.2依賴注入依賴注入是許多框架都有的功能。依賴是指一個(gè)類依賴另一個(gè)類的對(duì)象,通過依賴注入可以將當(dāng)前類依賴的對(duì)象注入進(jìn)來以便使用。8.4.2依賴注入指框架通過類的構(gòu)造方法的參數(shù)為類注入依賴的對(duì)象8.4.2依賴注入依賴注入構(gòu)造方法的依賴注入普通方法的依賴注入指框架通過類的普通方法的參數(shù)為類注入依賴的對(duì)象下面演示使用依賴注入和不使用依賴注入的區(qū)別。8.4.2依賴注入8.4.2依賴注入不使用依賴注入publicfunction__construct(){$this->request=newRequest();}使用依賴注入publicfunction__construct(Request$request){$this->request=$request;}直接通過構(gòu)造方法的參數(shù)接收依賴的Request類的對(duì)象構(gòu)造方法中實(shí)例化Request類,Request類的對(duì)象會(huì)被重復(fù)創(chuàng)建。

先定一個(gè)小目標(biāo)!掌握反射的實(shí)現(xiàn),能夠在自定義框架中實(shí)現(xiàn)依賴注入。8.4.3【案例】利用反射實(shí)現(xiàn)依賴注入了解了反射API和依賴注入后,接下來在自定義框架中實(shí)現(xiàn)依賴注入。自定義框架需要借助反射API獲取構(gòu)造方法和普通方法依賴的對(duì)象,將依賴的對(duì)象創(chuàng)建后注入。

案例需求8.4.3【案例】利用反射實(shí)現(xiàn)依賴注入①實(shí)現(xiàn)構(gòu)造方法的依賴注入。修改myframe\Container.php的make()方法,創(chuàng)建對(duì)象前使用ReflectionClass類獲取構(gòu)造方法的參數(shù),根據(jù)參數(shù)獲取類名,實(shí)例化該構(gòu)造方法依賴的類并完成依賴注入。②實(shí)現(xiàn)普通方法的依賴注入。修改myframe\App.php的dispatch()方法,創(chuàng)建普通方法前使用ReflectionMethod類獲取普通方法依賴的對(duì)象,在調(diào)用普通方法時(shí)傳入依賴的對(duì)象,完成依賴注入。

實(shí)現(xiàn)思路8.4.3【案例】利用反射實(shí)現(xiàn)依賴注入異常處理8.5

先定一個(gè)小目標(biāo)!掌握異常的拋出和捕獲,能夠在程序中拋出和捕獲異常。8.5.1異常的拋出和捕獲PHP提供了Exception類表示程序中的異常,通過實(shí)例化該類可以創(chuàng)建異常對(duì)象,創(chuàng)建后的異常對(duì)象使用throw關(guān)鍵字拋出。語(yǔ)法格式$e=newException('異常信息');throw$e;可以簡(jiǎn)寫成:thrownewException('異常信息');8.5.1異常的拋出和捕獲使用try…catch語(yǔ)句可以捕獲程序中拋出的異常并進(jìn)行處理。語(yǔ)法格式try{//可能會(huì)拋出異常的代碼}catch(Exception$e){//進(jìn)行異常處理的代碼}catch塊后面還可以添加finally塊,無論程序是否發(fā)生異常,finally塊中的代碼都會(huì)執(zhí)行。如果不需要finally塊,可以將其省略。8.5.1異常的拋出和捕獲使用try…catch語(yǔ)句的注意事項(xiàng):每個(gè)try塊應(yīng)至少有一個(gè)對(duì)應(yīng)的catch塊或finally塊。catch塊可以有多個(gè),用于針對(duì)不同的異常類型進(jìn)行處理,捕獲到異常后執(zhí)行對(duì)應(yīng)的catch塊。發(fā)生異常時(shí),PHP會(huì)嘗試查找第一個(gè)匹配的catch塊來執(zhí)行,如果直到腳本結(jié)束時(shí)都沒有找到匹配的catch塊且無finally塊,將會(huì)出現(xiàn)Fatalerror錯(cuò)誤。8.5.1異常的拋出和捕獲<?phpfunctiondivision($num1,$num2) {if(!$num2){

thrownewException('除數(shù)不能為0'); //拋出異常

echo'拋出異常后,后面的代碼不執(zhí)行。'; //測(cè)試此行代碼是否會(huì)執(zhí)行

}return$num1/$num2;}STEP01創(chuàng)建exception01.php文件。8.5.1異常的拋出和捕獲try{echodivision(1,0); //調(diào)用函數(shù)

echo'當(dāng)上一行代碼拋出異常時(shí),后面的代碼不會(huì)執(zhí)行';}catch(Exception$e){ //Exception表示異常類,$e表示異常對(duì)象

echo$e->getMessage(); //獲取異常信息}finally{echo'<br>異常處理完成';}echo'<br>異常處理完成后,后面的代碼會(huì)繼續(xù)執(zhí)行';STEP02在try塊調(diào)用division()函數(shù)時(shí),第2個(gè)參數(shù)設(shè)為0,在catch塊輸出異常信息,在finally塊中換行輸出“異常處理完成”。8.5.1異常的拋出和捕獲STEP03exception01.php文件的運(yùn)行結(jié)果。8.5.1異常的拋出和捕獲

先定一個(gè)小目標(biāo)!掌握自定義異常類的實(shí)現(xiàn),能夠根據(jù)需求實(shí)現(xiàn)自定義異常類。8.5.2自定義異常類自定義異常類用于表示特定類型的異常。自定義的異常類需要繼承Exception類,在自定義異常類中可以根據(jù)需求完成異常處理。下面演示如何自定義異常類,具體步驟如下。8.5.2自定義異常類<?phpclassMyExceptionextendsException{protected$msg='自定義異常信息';publicfunctiongetCustomMessage(){return$this->getMessage()?:$this->msg;}}STEP01創(chuàng)建MyException.php文件。8.5.2自定義異常類<?phprequire'./MyException.php';$email='myframe.test';try{if(!filter_var($email,FILTER_VALIDATE_EMAIL)){thrownewMyException('E-mail地址不合法');}}catch(MyException$e){

echo$e->getCustomMessage(); //輸出結(jié)果:E-mail地址不合法}STEP02創(chuàng)建exception02.php文件。8.5.2自定義異常類

先定一個(gè)小目標(biāo)!掌握多異常捕獲處理,能夠在程序中實(shí)現(xiàn)多異常的捕獲處理。8.5.3多異常捕獲處理一個(gè)try塊除了對(duì)應(yīng)一個(gè)catch塊外,還可以對(duì)應(yīng)多個(gè)catch塊。在catch塊中使用throw關(guān)鍵字拋出異常時(shí),可以使用不同的異常類對(duì)象返回不同的描述信息。8.5.3多異常捕獲處理演示多異常的捕獲處理:8.5.3多異常捕獲處理require'./MyException.php';$email='tom@';try{if(!filter_var($email,FILTER_VALIDATE_EMAIL)){thrownewException('E-mail地址不合法');}elseif(substr($email,strrpos($email,'@')+1)===''){thrownewMyException('不能使用作為郵箱地址');}}catch(MyException$e){echo$e->getCustomMessage();//輸出結(jié)果:不能使用作為郵箱地址}catch(Exception$e){echo$e->getMessage();

//輸出結(jié)果:E-mail地址不合法}

先定一個(gè)小目標(biāo)!掌握異常嵌套的實(shí)現(xiàn),能夠在程序中使用異常嵌套。8.5.4異常嵌套異常嵌套是指在一個(gè)try塊中嵌套try…catch語(yǔ)句。例如,PHP拋出的異常信息對(duì)用戶來說并不友好,可在捕獲異常后,再次拋出異常,返回給用戶更加友好的提示信息。8.5.4異常嵌套演示異常嵌套:<?phprequire'./MyException.php';try{

try{thrownewException();}catch(Exception$e){thrownewMyException('發(fā)生異常,請(qǐng)稍后再試');}}catch(MyException$e){echo$e->getMessage(); //輸出結(jié)果:發(fā)生異常,請(qǐng)稍后再試}8.5.4異常嵌套多學(xué)一招:set_exception_handler()函數(shù)set_exception_handler()函數(shù)在實(shí)際開發(fā)中,為了保證程序正常運(yùn)行,會(huì)在所有可能出現(xiàn)異常的地方使用try…catch語(yǔ)句進(jìn)行異常監(jiān)視,但是程序出現(xiàn)異常的地方總是無法預(yù)料的。為了保證程序能夠正常運(yùn)行,可以使用set_exception_handler()函數(shù)處理沒有進(jìn)行過異常處理的代碼。使用未引入的類中的方法代碼如下:functionexception_handler($e){echo$e->getMessage(); //輸出結(jié)果:Class'MyException'notfound}set_exception_handler('exception_handler');

先定一個(gè)小目標(biāo)!掌握在框架中處理異常的方法,能夠根據(jù)需求在框架中處理異常。8.5.5【案例】在框架中處理異常在項(xiàng)目開發(fā)階段,開發(fā)人員通常會(huì)直接在頁(yè)面中輸出錯(cuò)誤信息來調(diào)試程序。但對(duì)于生產(chǎn)環(huán)境的項(xiàng)目,直接顯示錯(cuò)誤報(bào)告可能會(huì)泄露服務(wù)器的重要信息。為了避免服務(wù)器信息泄露,下面在自定義框架中實(shí)現(xiàn)異常處理。

案例需求8.5.5【案例】在框架中處理異常①在App類中添加$debug屬性,表示是否開啟異常處理,默認(rèn)值為true表示開啟,值為false表示關(guān)閉,只有開啟才會(huì)顯示詳細(xì)的錯(cuò)誤報(bào)告。②修改App類的run()方法,將原有代碼寫在try塊中,在catch塊中捕獲異常。③修改App類的routeCheck()方法、controller()方法、dispatch()方法,使用Exception類拋出異常。

實(shí)現(xiàn)思路8.5.5【案例】在框架中處理異常本章小結(jié)本章主要講解了自定義框架的自動(dòng)加載、框架底層代碼的實(shí)現(xiàn)、反射API,以及異常的處理。通過本章的學(xué)習(xí),讀者應(yīng)熟悉框架的工作原理,能夠?qū)崿F(xiàn)自定義框架的基礎(chǔ)搭建和異常處理。本章小結(jié)第9章PDO擴(kuò)展和Smarty模板引擎《PHP網(wǎng)站開發(fā)實(shí)例教程(第3版)》學(xué)習(xí)目標(biāo)/Target

掌握PDO擴(kuò)展的使用方法,能夠使用PDO擴(kuò)展操作數(shù)據(jù)庫(kù)。

掌握數(shù)據(jù)庫(kù)操作類的封裝,能夠在自定義框架中封裝數(shù)據(jù)庫(kù)操作類。

掌握Smarty模板引擎的使用方法,能夠在自定義框架中使用Smarty模板引擎。章節(jié)概述/Summary在第7章和第8章中,我們已經(jīng)創(chuàng)建好了自定義框架并且完成了框架的基本功能。為了能夠在框架中操作數(shù)據(jù)庫(kù)和渲染數(shù)據(jù),本章將介紹PDO擴(kuò)展和Smarty模板引擎,在自定義框架中封裝數(shù)據(jù)庫(kù)操作類和使用Smarty模板引擎。目錄/Contents9.19.29.3PDO擴(kuò)展在自定義框架中封裝數(shù)據(jù)庫(kù)操作類Smarty模板引擎PDO擴(kuò)展9.1

先定一個(gè)小目標(biāo)!了解開啟PDO擴(kuò)展的方法,能夠開啟PDO擴(kuò)展。9.1.1開啟PDO擴(kuò)展PDO擴(kuò)展為PHP操作數(shù)據(jù)庫(kù)定義了一個(gè)輕量級(jí)的接口,從而可以用一套相同的接口操作不同的數(shù)據(jù)庫(kù)。目前支持的數(shù)據(jù)庫(kù)包括Firebird、FreeTDS、MySQL、MicrosoftSQLServer、Oracle、PostgreSQL、SQLite、Sybase等。9.1.1開啟PDO擴(kuò)展PDO支持的每個(gè)數(shù)據(jù)庫(kù)都對(duì)應(yīng)不同的擴(kuò)展文件。如果想讓PDO支持MySQL數(shù)據(jù)庫(kù),需要修改如下配置:extension=pdo_mysql9.1.1開啟PDO擴(kuò)展

先定一個(gè)小目標(biāo)!掌握連接和選擇數(shù)據(jù)庫(kù)的方法,能夠使用PDO類連接和選擇數(shù)據(jù)庫(kù)。9.1.2連接和選擇數(shù)據(jù)庫(kù)PDO擴(kuò)展提供了PDO類,能夠用于連接和操作數(shù)據(jù)庫(kù)。使用PDO類操作數(shù)據(jù)庫(kù)前,需要先實(shí)例化PDO類,傳遞連接數(shù)據(jù)庫(kù)的參數(shù):語(yǔ)法格式PDO::__construct(

string$dsn, //數(shù)據(jù)源名稱 string$username,//用戶名(可選參數(shù))string$password,//密碼(可選參數(shù)) array$driver_options //包含鍵值的驅(qū)動(dòng)連接選項(xiàng)(可選參數(shù)))9.1.2連接和選擇數(shù)據(jù)庫(kù)$dsn由PDO驅(qū)動(dòng)程序名稱、冒號(hào)和PDO驅(qū)動(dòng)程序特有的連接語(yǔ)法組成。例如,連接MySQL數(shù)據(jù)庫(kù)時(shí),PDO驅(qū)動(dòng)程序名稱為mysql,它特有的連接語(yǔ)法包括主機(jī)名、端口號(hào)、數(shù)據(jù)庫(kù)名稱、字符集等;連接Oracle數(shù)據(jù)庫(kù)時(shí),PDO驅(qū)動(dòng)程序名稱為oci,它特有的連接語(yǔ)法只包括數(shù)據(jù)庫(kù)名稱和字符集。MySQL數(shù)據(jù)庫(kù)和Oracle數(shù)據(jù)庫(kù)的$dsn如下:$mysqldsn='mysql:host=主機(jī)名;port=端口號(hào);dbname=數(shù)據(jù)庫(kù)名稱;charset=字符集';$oracledsn='oci:dbname=數(shù)據(jù)庫(kù)名稱;charset=字符集';9.1.2連接和選擇數(shù)據(jù)庫(kù)創(chuàng)建pdo01.php文件,使用PDO連接MySQL服務(wù)器并選擇myframe數(shù)據(jù)庫(kù):<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');var_dump($pdo);//輸出結(jié)果:object(PDO)#1(0){}9.1.2連接和選擇數(shù)據(jù)庫(kù)

先定一個(gè)小目標(biāo)!掌握?qǐng)?zhí)行SQL語(yǔ)句的方法,能夠使用query()方法和exec()方法執(zhí)行SQL語(yǔ)句。9.1.3執(zhí)行SQL語(yǔ)句PDO類對(duì)象的query()方法和exec()方法用于執(zhí)行SQL語(yǔ)句。這兩個(gè)方法的區(qū)別:query()方法返回的是PDOStatement類對(duì)象,該對(duì)象主要用于解析結(jié)果集、實(shí)現(xiàn)預(yù)處理和事務(wù)處理等;exec()方法返回的是受影響行數(shù),使用exec()方法執(zhí)行SELECT語(yǔ)句時(shí)不會(huì)返回查詢結(jié)果。通常使用query()方法執(zhí)行查詢類的SQL語(yǔ)句;使用exec()方法執(zhí)行操作類的SQL語(yǔ)句。執(zhí)行SQL語(yǔ)句后,使用lastInsertId()方法獲取最后插入行的id值。9.1.3執(zhí)行SQL語(yǔ)句修改pdo01.php文件,使用query()方法和exec()方法執(zhí)行SQL語(yǔ)句:<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$sql='SELECT*FROM`student`';var_dump($pdo->query($sql));//輸出結(jié)果:object(PDOStatement)#2(1){["queryString"]=>string(23)"SELECT*FROM`student`"}$sql="INSERTINTO`student`(`name`)VALUES('Leon')";var_dump($pdo->exec($sql)); //輸出結(jié)果:int(1)var_dump($pdo->lastInsertId()); //輸出結(jié)果:string(1)"5"9.1.3執(zhí)行SQL語(yǔ)句

先定一個(gè)小目標(biāo)!掌握處理結(jié)果集的方法,能夠使用不同方法處理結(jié)果集。9.1.4處理結(jié)果集使用query()方法執(zhí)行SQL語(yǔ)句后,返回的結(jié)果是PDOStatement類對(duì)象。通過PDOStatement類對(duì)象可以對(duì)結(jié)果集進(jìn)行處理,常用的處理結(jié)果集的方法有fetch()、fetchColumn()和fetchAll()。下面對(duì)這3個(gè)方法分別進(jìn)行講解。9.1.4處理結(jié)果集1.fetch()fetch()方法用于從結(jié)果集中獲取下一行數(shù)據(jù)。9.1.4處理結(jié)果集語(yǔ)法格式PDOStatement::fetch(int$mode=PDO::FETCH_DEFAULT, //返回方式(可選參數(shù))int$cursorOrientation=PDO::FETCH_ORI_NEXT,//可滾動(dòng)游標(biāo)(可選參數(shù))int$cursorOffset=0

//游標(biāo)的偏移量(可選參數(shù)))$mode的值必須是PDO::FETCH_*系列常量中的一個(gè),$mode的可選值:9.1.4處理結(jié)果集可選值說明返回值PDO::FETCH_ASSOC以關(guān)聯(lián)數(shù)組的方式提取結(jié)果集中的數(shù)據(jù)每一行的數(shù)據(jù)將被返回為一個(gè)關(guān)聯(lián)數(shù)組,其中鍵是列名,值是對(duì)應(yīng)的數(shù)據(jù)值PDO::FETCH_NUM以索引數(shù)組的方式提取結(jié)果集中的數(shù)據(jù)每一行的數(shù)據(jù)將被返回為一個(gè)索引數(shù)組,其中索引從0開始,值為對(duì)應(yīng)的數(shù)據(jù)值PDO::FETCH_BOTH同時(shí)以關(guān)聯(lián)數(shù)組和索引數(shù)組的方式提取結(jié)果集中的數(shù)據(jù)每一行的數(shù)據(jù)將被返回為一個(gè)混合數(shù)組,其中既包含字符串鍵名也包含數(shù)字鍵名,即每個(gè)列名對(duì)應(yīng)兩個(gè)鍵名PDO::FETCH_OBJ以匿名對(duì)象的方式提取結(jié)果集中的數(shù)據(jù)每一行的數(shù)據(jù)將被返回為一個(gè)匿名對(duì)象,其中屬性名對(duì)應(yīng)列名,屬性值對(duì)應(yīng)數(shù)據(jù)值1/2$mode的值必須是PDO::FETCH_*系列常量中的一個(gè),$mode的可選值:9.1.4處理結(jié)果集可選值說明返回值PDO::FETCH_LAZY以延遲加載的方式提取結(jié)果集中的數(shù)據(jù),只有在訪問數(shù)據(jù)時(shí)才會(huì)從數(shù)據(jù)庫(kù)中取出在訪問數(shù)據(jù)時(shí),會(huì)返回一個(gè)包含該行數(shù)據(jù)的對(duì)象,對(duì)象的屬性名對(duì)應(yīng)列名,屬性值對(duì)應(yīng)數(shù)據(jù)值PDO::FETCH_BOUND將結(jié)果集中的列值分配給PDOStatement::bindColumn()方法綁定的變量返回true,并分配結(jié)果集中的列值給PDOStatement::bindColumn()方法綁定的PHP變量PDO::FETCH_CLASS將結(jié)果集中的數(shù)據(jù)映射為指定請(qǐng)求類的實(shí)例返回一個(gè)請(qǐng)求類的實(shí)例,其中的屬性會(huì)被賦值為結(jié)果集中對(duì)應(yīng)的列值PDO::FETCH_INTO將結(jié)果集中的數(shù)據(jù)映射為指定被請(qǐng)求類的實(shí)例返回一個(gè)被請(qǐng)求類已存在的實(shí)例,其中命名的屬性會(huì)被賦值為結(jié)果集中對(duì)應(yīng)的列2/2創(chuàng)建pdo02.php文件,使用fetch()方法獲取查詢的數(shù)據(jù)的代碼及運(yùn)行結(jié)果:<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$sql='SELECT`id`,`name`FROM`student`LIMIT2';$res=$pdo->query($sql);while($row=$res->fetch(PDO::FETCH_ASSOC)){echo$row['id'].'-'.$row['name'].'<br>';}9.1.4處理結(jié)果集2.fetchColumn()fetchColumn()方法用于獲取結(jié)果集中的單獨(dú)一列,該方法執(zhí)行成功返回獲取的數(shù)據(jù),執(zhí)行失敗返回false。9.1.4處理結(jié)果集語(yǔ)法格式stringPDOStatement::fetchColumn(int$column=0)修改pdo02.php文件,使用fetchColumn()方法獲取結(jié)果集中的第2列數(shù)據(jù):while($column=$res->fetchColumn(1)){echo''.$column; //輸出結(jié)果:AllenJames}9.1.4處理結(jié)果集3.fetchAll()fetchAll()方法用于獲取結(jié)果集中所有的行數(shù)據(jù)。9.1.4處理結(jié)果集語(yǔ)法格式arrayPDOStatement::fetchAll(int$mode, //返回方式(可選參數(shù))mixed$fetch_argument, //可滾動(dòng)游標(biāo)(可選參數(shù))array$ctor_args=array() //PDO::FETCH_CLASS的參數(shù)(可選參數(shù)))$fetch_argument根據(jù)$mode參數(shù)值的變化而有不同意義,$mode的可選值:9.1.4處理結(jié)果集可選值作用返回值PDO::FETCH_COLUMN提取結(jié)果集中的單個(gè)列的值返回指定索引位置的列值,索引從0開始計(jì)數(shù)PDO::FETCH_CLASS將結(jié)果集中的數(shù)據(jù)映射為指定類的對(duì)象返回一個(gè)指定類的對(duì)象,其中的屬性會(huì)被賦值為結(jié)果集中對(duì)應(yīng)的列值PDO::FETCH_FUNC使用自定義的回調(diào)函數(shù)處理結(jié)果集中的每一行數(shù)據(jù)返回回調(diào)函數(shù)處理后的結(jié)果修改pdo02.php,使用fetchAll()方法以關(guān)聯(lián)數(shù)組形式獲取結(jié)果集:$data=$res->fetchAll(PDO::FETCH_ASSOC);print_r($data);9.1.4處理結(jié)果集輸出結(jié)果:Array([0]=>Array([id]=>1[name]=>Allen)[1]=>Array([id]=>2[name]=>James))多學(xué)一招:將變量綁定到結(jié)果集中的某一列將變量綁定到結(jié)果集中的某一列fetch()方法的參數(shù)設(shè)置為PDO::FETCH_BOUND時(shí),執(zhí)行成功后會(huì)分配結(jié)果集中的列值給bindColumn()方法綁定的變量。將變量綁定到結(jié)果集中的某一列的示例代碼:$res->bindColumn('id',$id);

//將變量$id綁定到結(jié)果集$res的id列$res->bindColumn('name',$name); //將變量$name綁定到結(jié)果集$res的name列while($res->fetch(PDO::FETCH_BOUND)){ //獲取綁定到變量中的數(shù)據(jù)

echo$id.'-'.$name.'<br>';}

先定一個(gè)小目標(biāo)!掌握預(yù)處理機(jī)制的使用,能夠使用指定方法創(chuàng)建預(yù)處理SQL語(yǔ)句和綁定數(shù)據(jù)。9.1.5預(yù)處理機(jī)制在PHP程序中編寫SQL語(yǔ)句時(shí),如果將發(fā)送的數(shù)據(jù)和SQL語(yǔ)句寫在一起,每條SQL語(yǔ)句都需要解析器進(jìn)行分析、編譯和優(yōu)化,效率低。預(yù)處理機(jī)制是先定義和發(fā)送模板形式的SQL語(yǔ)句,用占位符替代實(shí)際數(shù)據(jù),稱為預(yù)處理SQL語(yǔ)句,解析器會(huì)預(yù)先編譯預(yù)處理SQL語(yǔ)句,再處理相關(guān)數(shù)據(jù)。使用預(yù)處理機(jī)制可以避免數(shù)據(jù)中有特殊字符(如單引號(hào))而導(dǎo)致的語(yǔ)法問題出現(xiàn),提高程序運(yùn)行效率。下面講解預(yù)處理機(jī)制中的預(yù)處理方法和數(shù)據(jù)綁定。9.1.5預(yù)處理機(jī)制1.預(yù)處理方法通過PDO中的預(yù)處理方法prepare()和execute()可以實(shí)現(xiàn)預(yù)處理機(jī)制。prepare()方法用于準(zhǔn)備預(yù)處理SQL語(yǔ)句,execute()方法用以執(zhí)行預(yù)處理語(yǔ)句。prepare()方法語(yǔ)法格式PDOStatementPDO::prepare(string$query,array$options=array())9.1.5預(yù)處理機(jī)制execute()方法語(yǔ)法格式PDOStatement::execute($input_parameters)$query是預(yù)處理SQL語(yǔ)句,該語(yǔ)句中動(dòng)態(tài)變化的量用占位符代替,占位符使用問號(hào)占位符“?”和參數(shù)占位符“:參數(shù)名稱”;

$options是可選參數(shù),設(shè)置一個(gè)或多個(gè)PDOStatement對(duì)象的屬性值$input_parameters是可選參數(shù),表示為預(yù)處理SQL語(yǔ)句中的占位符綁定數(shù)據(jù),如果預(yù)處理SQL語(yǔ)句不包含占位符,可省略此參數(shù)。演示如何使用預(yù)處理方法:9.1.5預(yù)處理機(jī)制<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$sql='SELECT*FROM`student`';$stmt=$pdo->prepare($sql);var_dump($stmt->execute()); //輸出結(jié)果:bool(true)2.數(shù)據(jù)綁定預(yù)處理SQL語(yǔ)句中有占位符時(shí),使用execute()方法、bindParam()方法和bindValue()方法為占位符綁定數(shù)據(jù)。bindParam()方法和bindValue()方法的區(qū)別:bindParam()方法將占位符綁定到指定的變量名上,使用execute()方法執(zhí)行預(yù)處理SQL語(yǔ)句時(shí),只需要修改變量名的值。bindValue()方法將值綁定到占位符上,使用execute()方法執(zhí)行預(yù)處理SQL語(yǔ)句時(shí),每修改一次值,都需要重復(fù)執(zhí)行一次bindValue()方法和execute()方法。9.1.5預(yù)處理機(jī)制(1)execute()方法execute()方法的參數(shù)$input_parameters是一個(gè)數(shù)組,該數(shù)組的元素個(gè)數(shù)必須與預(yù)處理SQL語(yǔ)句中的占位符數(shù)量相同。當(dāng)占位符是問號(hào)占位符時(shí),$input_parameters必須是一個(gè)索引數(shù)組;當(dāng)占位符是參數(shù)占位符時(shí),$input_parameters必須是一個(gè)關(guān)聯(lián)數(shù)組。使用execute()方法為問號(hào)占位符綁定數(shù)據(jù):<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$sql='INSERTINTO`student`(`name`,`mobile`)VALUES(?,?)';$stmt=$pdo->prepare($sql);$stmt->execute(['Charles','1111']);$stmt->execute(['Andy','2222']);$stmt->execute(['Bruce','3333']);9.1.5預(yù)處理機(jī)制使用execute()方法為參數(shù)占位符綁定數(shù)據(jù):$sql='INSERTINTO`student`(`name`,`mobile`)VALUES'.'(:name,:mobile)';$stmt=$pdo->prepare($sql);$stmt->execute([':name'=>'Charles',':mobile'=>'1111']);$stmt->execute([':name'=>'Andy',':mobile'=>'2222']);$stmt->execute(['name'=>'Bruce','mobile'=>'3333']);9.1.5預(yù)處理機(jī)制為參數(shù)占位符綁定數(shù)據(jù)可以使用“:參數(shù)名”或“參數(shù)名”的形式(2)bindParam()方法使用bindParam()方法為問號(hào)占位符綁定數(shù)據(jù)時(shí),bindParam()方法的第1個(gè)參數(shù)是一個(gè)以1開始的數(shù)字,表示對(duì)應(yīng)預(yù)處理中的第幾個(gè)問號(hào)占位符,使用bindParam()方法為參數(shù)占位符綁定數(shù)據(jù)時(shí),bindParam()方法的第1個(gè)參數(shù)是“:參數(shù)名”或“參數(shù)名”的形式。使用bindParam()方法為問號(hào)占位符和參數(shù)占位符綁定數(shù)據(jù)://綁定問號(hào)占位符$stmt->bindParam(1,$name);$stmt->bindParam(2,$entry_date);//綁定參數(shù)占位符$stmt->bindParam(':參數(shù)名',$name);$stmt->bindParam('參數(shù)名',$entry_date);//省略“:”9.1.5預(yù)處理機(jī)制將占位符綁定指定的變量后,即可進(jìn)行變量的賦值和預(yù)處理SQL語(yǔ)句的執(zhí)行:list($name,$entry_date)=['Charles','2019-1-1'];$stmt->execute();list($name,$entry_date)=['Andy','2019-1-1'];$stmt->execute();9.1.5預(yù)處理機(jī)制(3)bindValue()方法bindValue()方法和bindParam()方法的第1個(gè)參數(shù)的使用方法相同,bindValue()方法的第2個(gè)參數(shù)用于傳入一個(gè)值,它無須進(jìn)行變量的綁定,使用較為方便。使用bindValue()方法為問號(hào)占位符和參數(shù)占位符綁定數(shù)據(jù)://綁定問號(hào)占位符$stmt->bindValue(1,'Charles');$stmt->bindValue(2,'2019-1-1');$stmt->execute();//綁定參數(shù)占位符$stmt->bindValue(':參數(shù)名','Charles');$stmt->bindValue('參數(shù)名','2019-1-1');//省略“:”$stmt->execute();9.1.5預(yù)處理機(jī)制

先定一個(gè)小目標(biāo)!掌握PDO錯(cuò)誤處理,能夠使用不同的錯(cuò)誤處理模式進(jìn)行錯(cuò)誤處理。9.1.6PDO錯(cuò)誤處理在使用SQL語(yǔ)句操作數(shù)據(jù)庫(kù)時(shí),難免會(huì)出現(xiàn)各種各樣的錯(cuò)誤,如語(yǔ)法錯(cuò)誤、邏輯錯(cuò)誤等。為了避免SQL語(yǔ)句出現(xiàn)這些錯(cuò)誤,我們既可以利用前面學(xué)習(xí)過的異常處理方式手動(dòng)捕獲PDOException類異常,也可以使用PDO提供的錯(cuò)誤處理模式進(jìn)行錯(cuò)誤處理。9.1.6PDO錯(cuò)誤處理PDO提供了3種錯(cuò)誤處理模式:①PDO::ERRMODE_SILENT:此模式表示在發(fā)生錯(cuò)誤時(shí)不進(jìn)行任何操作,只簡(jiǎn)單地設(shè)置錯(cuò)誤代碼。通過PDO類的errorCode()方法和errorInfo()方法獲取最后一次操作的錯(cuò)誤碼和錯(cuò)誤信息。②PDO::ERRMODE_WARNING:此模式表示在發(fā)生錯(cuò)誤時(shí),將錯(cuò)誤作為警告拋出,不中斷程序的運(yùn)行。③PDO::ERRMODE_EXCEPTION:此模式是默認(rèn)的錯(cuò)誤處理模式,它表示在錯(cuò)誤發(fā)生時(shí)拋出相關(guān)異常。此模式在項(xiàng)目調(diào)試當(dāng)中較為實(shí)用,可以快速地找到存在問題的代碼。9.1.6PDO錯(cuò)誤處理setAttribute()方法用于設(shè)置PDO的屬性,在程序中使用該方法設(shè)置錯(cuò)誤處理模式。語(yǔ)法格式PDO::setAttribute(PDO::ATTR_ERRMODE,$value);PDO::ATTR_ERRMODE表示設(shè)置錯(cuò)誤處理模式,$value表示設(shè)為哪種錯(cuò)誤處理模式,如PDO::ERRMODE_WARNING。9.1.6PDO錯(cuò)誤處理演示如何設(shè)置WARNING錯(cuò)誤處理模式:<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');//設(shè)置錯(cuò)誤模式$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);//預(yù)處理SQL語(yǔ)句$stmt=$pdo->prepare('SELECT*FROM`test`');//執(zhí)行預(yù)處理SQL語(yǔ)句,若execute()方法返回false表示執(zhí)行失敗if(false===$stmt->execute()){echo'錯(cuò)誤碼:'.$stmt->errorCode().'<br>'; //輸出錯(cuò)誤碼

print_r($stmt->errorInfo()); //輸出錯(cuò)誤信息}9.1.6PDO錯(cuò)誤處理上述代碼運(yùn)行結(jié)果:9.1.6PDO錯(cuò)誤處理多學(xué)一招:PDO屬性的獲取PDO屬性的獲取使用PDO類提供的getAttribute()方法可以獲取PDO連接的特定屬性的值,用于查詢和檢索與數(shù)據(jù)庫(kù)連接相關(guān)的各種屬性。getAttribute()方法的語(yǔ)法格式:PDO::getAttribute($attribute);$attribute用于指定要獲取的屬性的常量值多學(xué)一招:PDO屬性的獲取PDO屬性的獲取getAttribute()方法中的常量值是PDO::ATTR_*系列常量中的一個(gè),$attribute的可選值如下:PDO::ATTR_AUTOCOMMIT:連接的自動(dòng)提交模式。PDO::ATTR_CASE:列名在結(jié)果集中的大小寫方式。PDO::ATTR_CLIENT_VERSION:客戶端庫(kù)版本。PDO::ATTR_CONNECTION_STATUS:連接狀態(tài)。PDO::ATTR_DRIVER_NAME:驅(qū)動(dòng)程序名稱。PDO::ATTR_SERVER_INFO:服務(wù)器信息。PDO::ATTR_SERVER_VERSION:數(shù)據(jù)庫(kù)服務(wù)器版本。多學(xué)一招:PDO屬性的獲取PDO屬性的獲取演示使用getAttribute()方法獲取PDO連接的特定屬性的值:$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$driver_name=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME);echo'驅(qū)動(dòng)程序名稱是'.$driver_name; //輸出結(jié)果:驅(qū)動(dòng)程序名稱是mysql$server_version=$pdo->getAttribute(PDO::ATTR_SERVER_VERSION);echo'服務(wù)器的版本是'.$server_version; //輸出結(jié)果:服務(wù)器的版本是8.0.32

先定一個(gè)小目標(biāo)!掌握PDO事務(wù)處理,能夠使用PDO類的事務(wù)處理的相關(guān)方法實(shí)現(xiàn)事務(wù)。9.1.7PDO事務(wù)處理PDO類提供了事務(wù)處理的相關(guān)方法:9.1.7PDO事務(wù)處理方法名說明PDO::beginTransaction()啟動(dòng)事務(wù)PDO::commit()提交事務(wù)PDO::inTransaction()檢查是否在事務(wù)內(nèi)PDO::rollBack()回滾事務(wù)演示如何進(jìn)行事務(wù)處理:9.1.7PDO事務(wù)處理<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction(); //開啟事務(wù)try{$stmt=$pdo->prepare('INSERTINTO`student`(`name`)VALUES(?)');

//執(zhí)行插入操作

$stmt->execute(['小明']);$pdo->commit(); //提交事務(wù)}catch(PDOException$e){

$pdo->rollBack(); //回滾事務(wù)echo'執(zhí)行失敗:'.$e->getMessage();}在自定義框架中封裝數(shù)據(jù)庫(kù)操作類9.2

先定一個(gè)小目標(biāo)!掌握封裝DB類的方法,能夠在自定義框架中封裝DB類。9.2.1【案例】封裝DB類在自定義框

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論