PHP网站开发实例教程(第3版) 课件 第8、9章 PHP框架基础(下)、PDO扩展和Smarty模板引擎_第1页
PHP网站开发实例教程(第3版) 课件 第8、9章 PHP框架基础(下)、PDO扩展和Smarty模板引擎_第2页
PHP网站开发实例教程(第3版) 课件 第8、9章 PHP框架基础(下)、PDO扩展和Smarty模板引擎_第3页
PHP网站开发实例教程(第3版) 课件 第8、9章 PHP框架基础(下)、PDO扩展和Smarty模板引擎_第4页
PHP网站开发实例教程(第3版) 课件 第8、9章 PHP框架基础(下)、PDO扩展和Smarty模板引擎_第5页
已阅读5页,还剩153页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章PHP框架基础(下)《PHP网站开发实例教程(第3版)》学习目标/Target

掌握Composer的使用,能够使用Composer管理项目。

掌握框架基础搭建,能够实现App类、Request类、Response类和Container类。

掌握反射API的使用方法,能够使用反射API实现反射。

掌握依赖注入的使用方法,能够利用反射实现依赖注入。

熟悉框架的目录结构,能够说出每个目录的作用。学习目标/Target

掌握异常的抛出和捕获,能够在程序中抛出和捕获异常。

掌握自定义异常类的实现,能够根据需求实现自定义异常类。

掌握多异常捕获处理,能够在程序中实现多异常的捕获处理。

掌握异常嵌套的实现,能够在程序中使用异常嵌套。章节概述/Summary学习了第7章的框架基础知识后,相信读者已经可以在自定义框架中实现指定的功能。为了让读者对框架有更深入的理解,本章将对框架的底层设计思想和实现原理进行讲解,内容包括划分框架目录结构、使用Composer管理项目、框架基础搭建、反射和异常处理。目录/Contents8.18.28.3划分框架目录结构使用Composer管理项目框架基础搭建8.4反射8.5异常处理划分框架目录结构8.1

先定一个小目标!熟悉框架的目录结构,能够说出每个目录的作用。8.1划分框架目录结构通常情况下,一个项目由许多不同类型的文件组成,为了更好地管理这些文件,需要划分目录结构。为了让自定义框架的目录结构更接近常用的PHP框架,本书参考Laravel框架的目录结构,对自定义框架进行目录划分,将自定义框架命名为myframe.test。8.1划分框架目录结构myframe.test框架的目录结构:├─app 框架核心目录│├─Http HTTP请求目录││├─Controllers 控制器目录│├─Models 模型目录├─resources 资源目录│├─views 视图目录├─public 公开目录├─myframe 框架目录├─vendor Composer依赖包目录(由Composer自动创建)8.1划分框架目录结构使用Composer管理项目8.2

先定一个小目标!掌握Composer的安装,能够独立安装Composer。8.2.1安装ComposerComposer是PHP项目中管理项目依赖的工具,开发人员在项目中声明依赖的外部工具库,Composer就会自动安装工具库依赖的库文件。大多数PHP框架都支持Composer。在Composer官方网站可以下载Composer。在Windows中安装Composer的方式有两种:使用安装程序安装使用命令行安装8.2.1安装Composer1在Composer官网下载Composer-Setup.exe,双击下载文件启动安装程序,选择推荐的安装模式。安装程序提示选择是否使用开发者模式,若选中此项不提供卸载功能,推荐不选中。2安装过程提示选择PHP命令行程序时,单击“Browse…”按钮浏览文件,选择C:\web\php8.2\php.exe。38.2.1安装Composer使用安装程序安装的步骤:4进入填写代理服务器界面,选择不使用代理,单击“Next”按钮。进入准备安装界面,单击“Install”按钮进行安装。5打开新的命令提示符窗口,执行“composer”命令测试Composer是否安装成功。68.2.1安装Composer使用安装程序安装的步骤:

先定一个小目标!掌握使用Composer实现自动加载的方法,能够在自定义框架中实现类的自动加载。8.2.2使用Composer实现自动加载虽然PHP提供了自动加载机制,但是要在项目中实现自动加载功能还需要手动编写代码,操作起来相对复杂。为了使开发更简单,可以在myframe.test项目中使用Composer实现类的自动加载。8.2.2使用Composer实现自动加载1在C:\web\www\myframe目录下创建composer.json文件,定义自动加载的命名空间。在命令提示符窗口中切换到composer.json文件所在目录,执行composerinstall命令安装依赖关系所需组件,初始化自动加载信息。2重新编写public\index.php文件,引入vendor\autoload.php文件实现自动加载。3在myframe.test项目中使用Composer实现类的自动加载具体步骤:8.2.2使用Composer实现自动加载4将原有的app\StudentController.php放入app\Http\Controllers目录。将原有的视图文件views\student.php移动到resources\views目录中。修改public\index.php文件,定义路由规则,根据路由找到对应的控制器名和方法名。56在myframe.test项目中使用Composer实现类的自动加载具体步骤:将原有的app\StudentModel.php修改为app\Models\Student.php。修改Student.php,将命名空间放在App下。8.2.2使用Composer实现自动加载

先定一个小目标!掌握使用Composer管理项目依赖的方法,能够使用Composer安装和卸载依赖包。8.2.3使用Composer管理项目依赖8.2.3使用Composer管理项目依赖在以前开发中,如果项目中使用了某个类库,需要手动下载这个类库的文件,并在代码中引入类库后才能使用。这种方式不仅麻烦,而且当类库的版本更新后,还需要重新下载类库。如果一个类库又依赖于另一个类库,这种层叠的依赖关系会让项目的维护变得复杂并且低效。为了解决手动下载类库这个问题,Composer提供了项目依赖管理功能,它可以自动完成依赖包的下载和安装,并通过命名空间自动引入。8.2.3使用Composer管理项目依赖Composer通过packagist资源库获取依赖包。在packagist资源库中,依赖包的命名方式为“用户名/包名”。例如“naux/auto-correct”包能够在中文和英文之间添加空格,并纠正专用名词的大小写。安装依赖包的两种方式使用composerrequire命令安装在配置文件中添加依赖包在composer.json文件中添加包的相关信息,在命令提示符窗口中执行composerinstall命令或执行composerupdate命令8.2.3使用Composer管理项目依赖通常情况下,一个包会有多个版本,指定版本号的多种方式:名称实例描述特定的版本3.1.33包的版本是3.1.33某个范围的版本~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等价8.2.3使用Composer管理项目依赖以naux/auto-correct包为例,演示使用Composer管理项目依赖:1安装依赖包需要开启zip扩展,在PHP配置文件php.ini开启zip扩展。在命令提示符窗口中切换到C:\web\www\myframe目录,执行composerrequire命令安装依赖包。2在app\Http\Controllers\StudentController.php中导入命名空间,编写test()方法。38.2.3使用Composer管理项目依赖test()方法的代码:第1种方式publicfunctiontest(){$correct=newAutoCorrect;//在中文和英文之间添加空格

echo$correct->auto_space('《php网站开发实例教程》');//纠正专用词汇的大小写

echo$correct->auto_correct('《php网站开发实例教程》');}输出结果:《php网站开发实例教程》《PHP网站开发实例教程》8.2.3使用Composer管理项目依赖如果想要卸载依赖包,可以使用如下命令:第1种方式composerremovenaux/auto-correct卸载依赖包会将依赖配置删除,并删除vendor目录中依赖包的相关文件。8.2.3使用Composer管理项目依赖

先定一个小目标!掌握使用Composer管理项目的方法,能够创建自己的包。8.2.4【案例】创建自己的包在进行项目开发时,除了可以使用Composer下载packagist中的依赖包外,还可以将自己实现的功能或项目打包成依赖包,完成测试后,将其发布到Packagist资源库中供其他人使用。下面通过案例演示如何使用Composer创建自己的包。

案例需求8.2.4【案例】创建自己的包①在C:\web\apache2.4\htdocs目录中创建包的基础目录custom-php-json,在该目录下创建src目录和src\Json.php文件,实现对数据的JSON编码和解码。②创建custom-php-json\composer.json文件,编写包的初始化信息。③在项目中使用创建的包,测试对数据的JSON编码和解码。

实现思路8.2.4【案例】创建自己的包框架基础搭建8.3

先定一个小目标!掌握框架基础搭建,能够实现App类。8.3.1App类App类的代码用于实现框架的启动。在前面的开发中,框架的启动是通过入口文件实现的,而将启动框架的核心代码放在App类中,可以使代码更加符合面向对象的思想。8.3.1App类实现App类的具体步骤:1准备工作在composer.json中添加命名空间配置,编写run()方法实现应用启动,在index.php中实例化App类并调用run()方法。路由检测根据用户请求的URL,检测对应的控制器名和方法名。例如,用户请求的URL:http://www.myframe.test/student/test,检测结果为Student控制器test()方法。2请求分发在App类中,根据路由检测的结果调用对应控制器和方法,实现请求分发。38.3.1App类

先定一个小目标!掌握框架基础搭建,能够实现Request类。8.3.2Request类Request类负责获取请求信息,它是对当前请求的封装。通过Request类可以获取$_GET、$_POST、$_SERVER等超全局变量中的数据。与直接访问超全局变量相比,使用Request类可以对所有的请求数据进行统一处理,提供一种面向对象、简单易用的操作方式。下面以获取$_SERVER超全局变量的请求信息为例进行讲解。8.3.2Request类实现Request类的具体步骤:1创建myframe\Request.php文件编写server()方法和pathinfo()方法,其中server()方法用于获取$_SERVER中的数据,pathinfo()方法用于解析PATH_INFO。在App类中使用Request类在App类中定义构造方法实例化Request类,修改routeCheck()方法,调用Request类的pathinfo()方法获取请求信息。28.3.2Request类

先定一个小目标!掌握框架基础搭建,能够实现Response类。8.3.3Response类Response类负责处理响应信息。将响应输出的代码封装到Response类中,开发人员不再需要使用其他输出语句输出数据,输出数据的工作由Response类处理。下面讲解如何实现Response类。8.3.3Response类实现Response类的具体步骤:1创建myframe\Response.php文件在类中定义$code、$header和$data属性,分别表示响应状态码、响应头和响应数据。实现Response类编写构造方法,在创建对象时传入基本参数,编写send()方法用于输出数据,编写create()静态方法用于创建本类对象。2使用Response类在App类的dispatch()方法中,接收控制器的返回结果并创建Response实例,在App类的run()方法中返回Response实例,在public\index.php中,修改启动应用的代码,调用send()方法将结果输出。38.3.3Response类

先定一个小目标!掌握框架基础搭建,能够实现Container类。8.3.4Container类在框架中,有许多类只希望被实例化一次,例如,数据库操作类。为了避免一个类被重复实例化,通常将这些类的对象放到容器中。Container类表示容器,它用于创建对象,并将创建的对象放在容器中,当再次创建相同类的对象时,如果容器中存在则直接返回,不必重复创建。下面讲解如何实现Container类。8.3.4Container类实现Container类的具体步骤:1创建myframe\Container.php文件创建make()方法用于创建对象,将对象保存在数组中,定义静态方法getInstance()创建自身对象,修改App类的构造方法,通过Container::getInstance()创建容器对象。使用Container类修改App类继承Container类,在构造方法中创建Request对象。28.3.4Container类反射8.4

先定一个小目标!掌握反射API的使用,能够使用反射API实现反射。8.4.1反射API反射是PHP针对面向对象编程提供的一种“自省”的过程。可以将其理解为根据“目的地”寻找“出发地或来源”。例如,对某个对象进行反射,找到这个对象所属的类、拥有的方法和属性、方法的参数、文档注释等详细信息。8.4.1反射API在PHP中使用反射,主要通过反射API来完成。反射API常用的类与接口:8.4.1反射API类/接口说明Reflection反射类Reflector反射接口ReflectionClass获取类的相关信息ReflectionObject获取对象的相关信息ReflectionMethod获取方法的相关信息ReflectionProperty获取类的属性的相关信息ReflectionParameter获取函数或方法参数的相关信息1/2在PHP中使用反射,主要通过反射API来完成。反射API常用的类与接口:8.4.1反射API类/接口实例ReflectionExtension获取扩展的相关信息ReflectionFunction获取函数的相关信息ReflectionFunctionAbstractReflectionFunction的父类ReflectionException用于反射异常处理ReflectionClassConstant获取类常量的信息ReflectionType获取参数或者返回值的类型2/2ReflectionClass类常用的方法:8.4.1反射API类名方法名功能描述ReflectionClassgetMethod()获取一个类方法的ReflectionMethod对象getName()获取类名getConstructor()获取类的构造函数getProperties()获取一组属性hasMethod()检查方法是否已定义hasProperty()检查属性是否已定义newInstance()通过指定的参数创建一个新的类实例newInstanceArgs()通过数组参数创建一个新的类实例ReflectionMethod类和ReflectionFunctionAbstract类常用的方法:8.4.1反射API类名方法名功能描述ReflectionMethodinvoke()实现执行操作invokeArgs()带参数执行isPublic()判断方法是不是公开方法ReflectionFunctionAbstractgetNumberOfParameters()获取参数数目getParameters获取参数ReflectionProperty类常用的方法:8.4.1反射API类名方法名功能描述ReflectionPropertygetDocComment()获取属性文档注释getName()获取属性名称getValue()获取属性值isDefault()检查属性是不是默认属性isPrivate()检查属性是不是私有属性isProtected()检查属性是不是保护属性isPublic()检查属性是不是公有属性isStatic()检查属性是不是静态属性ReflectionParameter类和ReflectionExtension类常用的方法:8.4.1反射API类名方法名功能描述ReflectionParametergetClass()获得类型提示类getDefaultValue()获取默认属性值ReflectionExtensiongetFunctions()获取扩展中的函数getINIEntries()获取ini配置getVersion()获取扩展版本号info()输出扩展信息8.4.1反射API下面演示如何使用反射获取类属性的信息,具体步骤如下。<?php//定义一个类,用于测试classUpload{/***上传文件信息*/private$file=[];/***上传文件保存目录*/public$upload_dir='/upload/';}8.4.1反射APISTEP01编写Upload.php文件。该文件用于后续通过反射来获取其基本信息。<?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创建reflect.php文件。引入Upload.php,获取Upload类的所有属性,输出其中的公有属性。获取Upload类的反射对象,通过反射对象调用getProperties()方法获取Upload类的所有属性8.4.1反射APISTEP03reflect.php文件的运行结果。

先定一个小目标!掌握依赖注入的使用,能够利用反射实现依赖注入。8.4.2依赖注入依赖注入是许多框架都有的功能。依赖是指一个类依赖另一个类的对象,通过依赖注入可以将当前类依赖的对象注入进来以便使用。8.4.2依赖注入指框架通过类的构造方法的参数为类注入依赖的对象8.4.2依赖注入依赖注入构造方法的依赖注入普通方法的依赖注入指框架通过类的普通方法的参数为类注入依赖的对象下面演示使用依赖注入和不使用依赖注入的区别。8.4.2依赖注入8.4.2依赖注入不使用依赖注入publicfunction__construct(){$this->request=newRequest();}使用依赖注入publicfunction__construct(Request$request){$this->request=$request;}直接通过构造方法的参数接收依赖的Request类的对象构造方法中实例化Request类,Request类的对象会被重复创建。

先定一个小目标!掌握反射的实现,能够在自定义框架中实现依赖注入。8.4.3【案例】利用反射实现依赖注入了解了反射API和依赖注入后,接下来在自定义框架中实现依赖注入。自定义框架需要借助反射API获取构造方法和普通方法依赖的对象,将依赖的对象创建后注入。

案例需求8.4.3【案例】利用反射实现依赖注入①实现构造方法的依赖注入。修改myframe\Container.php的make()方法,创建对象前使用ReflectionClass类获取构造方法的参数,根据参数获取类名,实例化该构造方法依赖的类并完成依赖注入。②实现普通方法的依赖注入。修改myframe\App.php的dispatch()方法,创建普通方法前使用ReflectionMethod类获取普通方法依赖的对象,在调用普通方法时传入依赖的对象,完成依赖注入。

实现思路8.4.3【案例】利用反射实现依赖注入异常处理8.5

先定一个小目标!掌握异常的抛出和捕获,能够在程序中抛出和捕获异常。8.5.1异常的抛出和捕获PHP提供了Exception类表示程序中的异常,通过实例化该类可以创建异常对象,创建后的异常对象使用throw关键字抛出。语法格式$e=newException('异常信息');throw$e;可以简写成:thrownewException('异常信息');8.5.1异常的抛出和捕获使用try…catch语句可以捕获程序中抛出的异常并进行处理。语法格式try{//可能会抛出异常的代码}catch(Exception$e){//进行异常处理的代码}catch块后面还可以添加finally块,无论程序是否发生异常,finally块中的代码都会执行。如果不需要finally块,可以将其省略。8.5.1异常的抛出和捕获使用try…catch语句的注意事项:每个try块应至少有一个对应的catch块或finally块。catch块可以有多个,用于针对不同的异常类型进行处理,捕获到异常后执行对应的catch块。发生异常时,PHP会尝试查找第一个匹配的catch块来执行,如果直到脚本结束时都没有找到匹配的catch块且无finally块,将会出现Fatalerror错误。8.5.1异常的抛出和捕获<?phpfunctiondivision($num1,$num2) {if(!$num2){

thrownewException('除数不能为0'); //抛出异常

echo'抛出异常后,后面的代码不执行。'; //测试此行代码是否会执行

}return$num1/$num2;}STEP01创建exception01.php文件。8.5.1异常的抛出和捕获try{echodivision(1,0); //调用函数

echo'当上一行代码抛出异常时,后面的代码不会执行';}catch(Exception$e){ //Exception表示异常类,$e表示异常对象

echo$e->getMessage(); //获取异常信息}finally{echo'<br>异常处理完成';}echo'<br>异常处理完成后,后面的代码会继续执行';STEP02在try块调用division()函数时,第2个参数设为0,在catch块输出异常信息,在finally块中换行输出“异常处理完成”。8.5.1异常的抛出和捕获STEP03exception01.php文件的运行结果。8.5.1异常的抛出和捕获

先定一个小目标!掌握自定义异常类的实现,能够根据需求实现自定义异常类。8.5.2自定义异常类自定义异常类用于表示特定类型的异常。自定义的异常类需要继承Exception类,在自定义异常类中可以根据需求完成异常处理。下面演示如何自定义异常类,具体步骤如下。8.5.2自定义异常类<?phpclassMyExceptionextendsException{protected$msg='自定义异常信息';publicfunctiongetCustomMessage(){return$this->getMessage()?:$this->msg;}}STEP01创建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(); //输出结果:E-mail地址不合法}STEP02创建exception02.php文件。8.5.2自定义异常类

先定一个小目标!掌握多异常捕获处理,能够在程序中实现多异常的捕获处理。8.5.3多异常捕获处理一个try块除了对应一个catch块外,还可以对应多个catch块。在catch块中使用throw关键字抛出异常时,可以使用不同的异常类对象返回不同的描述信息。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();//输出结果:不能使用作为邮箱地址}catch(Exception$e){echo$e->getMessage();

//输出结果:E-mail地址不合法}

先定一个小目标!掌握异常嵌套的实现,能够在程序中使用异常嵌套。8.5.4异常嵌套异常嵌套是指在一个try块中嵌套try…catch语句。例如,PHP抛出的异常信息对用户来说并不友好,可在捕获异常后,再次抛出异常,返回给用户更加友好的提示信息。8.5.4异常嵌套演示异常嵌套:<?phprequire'./MyException.php';try{

try{thrownewException();}catch(Exception$e){thrownewMyException('发生异常,请稍后再试');}}catch(MyException$e){echo$e->getMessage(); //输出结果:发生异常,请稍后再试}8.5.4异常嵌套多学一招:set_exception_handler()函数set_exception_handler()函数在实际开发中,为了保证程序正常运行,会在所有可能出现异常的地方使用try…catch语句进行异常监视,但是程序出现异常的地方总是无法预料的。为了保证程序能够正常运行,可以使用set_exception_handler()函数处理没有进行过异常处理的代码。使用未引入的类中的方法代码如下:functionexception_handler($e){echo$e->getMessage(); //输出结果:Class'MyException'notfound}set_exception_handler('exception_handler');

先定一个小目标!掌握在框架中处理异常的方法,能够根据需求在框架中处理异常。8.5.5【案例】在框架中处理异常在项目开发阶段,开发人员通常会直接在页面中输出错误信息来调试程序。但对于生产环境的项目,直接显示错误报告可能会泄露服务器的重要信息。为了避免服务器信息泄露,下面在自定义框架中实现异常处理。

案例需求8.5.5【案例】在框架中处理异常①在App类中添加$debug属性,表示是否开启异常处理,默认值为true表示开启,值为false表示关闭,只有开启才会显示详细的错误报告。②修改App类的run()方法,将原有代码写在try块中,在catch块中捕获异常。③修改App类的routeCheck()方法、controller()方法、dispatch()方法,使用Exception类抛出异常。

实现思路8.5.5【案例】在框架中处理异常本章小结本章主要讲解了自定义框架的自动加载、框架底层代码的实现、反射API,以及异常的处理。通过本章的学习,读者应熟悉框架的工作原理,能够实现自定义框架的基础搭建和异常处理。本章小结第9章PDO扩展和Smarty模板引擎《PHP网站开发实例教程(第3版)》学习目标/Target

掌握PDO扩展的使用方法,能够使用PDO扩展操作数据库。

掌握数据库操作类的封装,能够在自定义框架中封装数据库操作类。

掌握Smarty模板引擎的使用方法,能够在自定义框架中使用Smarty模板引擎。章节概述/Summary在第7章和第8章中,我们已经创建好了自定义框架并且完成了框架的基本功能。为了能够在框架中操作数据库和渲染数据,本章将介绍PDO扩展和Smarty模板引擎,在自定义框架中封装数据库操作类和使用Smarty模板引擎。目录/Contents9.19.29.3PDO扩展在自定义框架中封装数据库操作类Smarty模板引擎PDO扩展9.1

先定一个小目标!了解开启PDO扩展的方法,能够开启PDO扩展。9.1.1开启PDO扩展PDO扩展为PHP操作数据库定义了一个轻量级的接口,从而可以用一套相同的接口操作不同的数据库。目前支持的数据库包括Firebird、FreeTDS、MySQL、MicrosoftSQLServer、Oracle、PostgreSQL、SQLite、Sybase等。9.1.1开启PDO扩展PDO支持的每个数据库都对应不同的扩展文件。如果想让PDO支持MySQL数据库,需要修改如下配置:extension=pdo_mysql9.1.1开启PDO扩展

先定一个小目标!掌握连接和选择数据库的方法,能够使用PDO类连接和选择数据库。9.1.2连接和选择数据库PDO扩展提供了PDO类,能够用于连接和操作数据库。使用PDO类操作数据库前,需要先实例化PDO类,传递连接数据库的参数:语法格式PDO::__construct(

string$dsn, //数据源名称 string$username,//用户名(可选参数)string$password,//密码(可选参数) array$driver_options //包含键值的驱动连接选项(可选参数))9.1.2连接和选择数据库$dsn由PDO驱动程序名称、冒号和PDO驱动程序特有的连接语法组成。例如,连接MySQL数据库时,PDO驱动程序名称为mysql,它特有的连接语法包括主机名、端口号、数据库名称、字符集等;连接Oracle数据库时,PDO驱动程序名称为oci,它特有的连接语法只包括数据库名称和字符集。MySQL数据库和Oracle数据库的$dsn如下:$mysqldsn='mysql:host=主机名;port=端口号;dbname=数据库名称;charset=字符集';$oracledsn='oci:dbname=数据库名称;charset=字符集';9.1.2连接和选择数据库创建pdo01.php文件,使用PDO连接MySQL服务器并选择myframe数据库:<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');var_dump($pdo);//输出结果:object(PDO)#1(0){}9.1.2连接和选择数据库

先定一个小目标!掌握执行SQL语句的方法,能够使用query()方法和exec()方法执行SQL语句。9.1.3执行SQL语句PDO类对象的query()方法和exec()方法用于执行SQL语句。这两个方法的区别:query()方法返回的是PDOStatement类对象,该对象主要用于解析结果集、实现预处理和事务处理等;exec()方法返回的是受影响行数,使用exec()方法执行SELECT语句时不会返回查询结果。通常使用query()方法执行查询类的SQL语句;使用exec()方法执行操作类的SQL语句。执行SQL语句后,使用lastInsertId()方法获取最后插入行的id值。9.1.3执行SQL语句修改pdo01.php文件,使用query()方法和exec()方法执行SQL语句:<?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));//输出结果:object(PDOStatement)#2(1){["queryString"]=>string(23)"SELECT*FROM`student`"}$sql="INSERTINTO`student`(`name`)VALUES('Leon')";var_dump($pdo->exec($sql)); //输出结果:int(1)var_dump($pdo->lastInsertId()); //输出结果:string(1)"5"9.1.3执行SQL语句

先定一个小目标!掌握处理结果集的方法,能够使用不同方法处理结果集。9.1.4处理结果集使用query()方法执行SQL语句后,返回的结果是PDOStatement类对象。通过PDOStatement类对象可以对结果集进行处理,常用的处理结果集的方法有fetch()、fetchColumn()和fetchAll()。下面对这3个方法分别进行讲解。9.1.4处理结果集1.fetch()fetch()方法用于从结果集中获取下一行数据。9.1.4处理结果集语法格式PDOStatement::fetch(int$mode=PDO::FETCH_DEFAULT, //返回方式(可选参数)int$cursorOrientation=PDO::FETCH_ORI_NEXT,//可滚动游标(可选参数)int$cursorOffset=0

//游标的偏移量(可选参数))$mode的值必须是PDO::FETCH_*系列常量中的一个,$mode的可选值:9.1.4处理结果集可选值说明返回值PDO::FETCH_ASSOC以关联数组的方式提取结果集中的数据每一行的数据将被返回为一个关联数组,其中键是列名,值是对应的数据值PDO::FETCH_NUM以索引数组的方式提取结果集中的数据每一行的数据将被返回为一个索引数组,其中索引从0开始,值为对应的数据值PDO::FETCH_BOTH同时以关联数组和索引数组的方式提取结果集中的数据每一行的数据将被返回为一个混合数组,其中既包含字符串键名也包含数字键名,即每个列名对应两个键名PDO::FETCH_OBJ以匿名对象的方式提取结果集中的数据每一行的数据将被返回为一个匿名对象,其中属性名对应列名,属性值对应数据值1/2$mode的值必须是PDO::FETCH_*系列常量中的一个,$mode的可选值:9.1.4处理结果集可选值说明返回值PDO::FETCH_LAZY以延迟加载的方式提取结果集中的数据,只有在访问数据时才会从数据库中取出在访问数据时,会返回一个包含该行数据的对象,对象的属性名对应列名,属性值对应数据值PDO::FETCH_BOUND将结果集中的列值分配给PDOStatement::bindColumn()方法绑定的变量返回true,并分配结果集中的列值给PDOStatement::bindColumn()方法绑定的PHP变量PDO::FETCH_CLASS将结果集中的数据映射为指定请求类的实例返回一个请求类的实例,其中的属性会被赋值为结果集中对应的列值PDO::FETCH_INTO将结果集中的数据映射为指定被请求类的实例返回一个被请求类已存在的实例,其中命名的属性会被赋值为结果集中对应的列2/2创建pdo02.php文件,使用fetch()方法获取查询的数据的代码及运行结果:<?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处理结果集2.fetchColumn()fetchColumn()方法用于获取结果集中的单独一列,该方法执行成功返回获取的数据,执行失败返回false。9.1.4处理结果集语法格式stringPDOStatement::fetchColumn(int$column=0)修改pdo02.php文件,使用fetchColumn()方法获取结果集中的第2列数据:while($column=$res->fetchColumn(1)){echo''.$column; //输出结果:AllenJames}9.1.4处理结果集3.fetchAll()fetchAll()方法用于获取结果集中所有的行数据。9.1.4处理结果集语法格式arrayPDOStatement::fetchAll(int$mode, //返回方式(可选参数)mixed$fetch_argument, //可滚动游标(可选参数)array$ctor_args=array() //PDO::FETCH_CLASS的参数(可选参数))$fetch_argument根据$mode参数值的变化而有不同意义,$mode的可选值:9.1.4处理结果集可选值作用返回值PDO::FETCH_COLUMN提取结果集中的单个列的值返回指定索引位置的列值,索引从0开始计数PDO::FETCH_CLASS将结果集中的数据映射为指定类的对象返回一个指定类的对象,其中的属性会被赋值为结果集中对应的列值PDO::FETCH_FUNC使用自定义的回调函数处理结果集中的每一行数据返回回调函数处理后的结果修改pdo02.php,使用fetchAll()方法以关联数组形式获取结果集:$data=$res->fetchAll(PDO::FETCH_ASSOC);print_r($data);9.1.4处理结果集输出结果:Array([0]=>Array([id]=>1[name]=>Allen)[1]=>Array([id]=>2[name]=>James))多学一招:将变量绑定到结果集中的某一列将变量绑定到结果集中的某一列fetch()方法的参数设置为PDO::FETCH_BOUND时,执行成功后会分配结果集中的列值给bindColumn()方法绑定的变量。将变量绑定到结果集中的某一列的示例代码:$res->bindColumn('id',$id);

//将变量$id绑定到结果集$res的id列$res->bindColumn('name',$name); //将变量$name绑定到结果集$res的name列while($res->fetch(PDO::FETCH_BOUND)){ //获取绑定到变量中的数据

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

先定一个小目标!掌握预处理机制的使用,能够使用指定方法创建预处理SQL语句和绑定数据。9.1.5预处理机制在PHP程序中编写SQL语句时,如果将发送的数据和SQL语句写在一起,每条SQL语句都需要解析器进行分析、编译和优化,效率低。预处理机制是先定义和发送模板形式的SQL语句,用占位符替代实际数据,称为预处理SQL语句,解析器会预先编译预处理SQL语句,再处理相关数据。使用预处理机制可以避免数据中有特殊字符(如单引号)而导致的语法问题出现,提高程序运行效率。下面讲解预处理机制中的预处理方法和数据绑定。9.1.5预处理机制1.预处理方法通过PDO中的预处理方法prepare()和execute()可以实现预处理机制。prepare()方法用于准备预处理SQL语句,execute()方法用以执行预处理语句。prepare()方法语法格式PDOStatementPDO::prepare(string$query,array$options=array())9.1.5预处理机制execute()方法语法格式PDOStatement::execute($input_parameters)$query是预处理SQL语句,该语句中动态变化的量用占位符代替,占位符使用问号占位符“?”和参数占位符“:参数名称”;

$options是可选参数,设置一个或多个PDOStatement对象的属性值$input_parameters是可选参数,表示为预处理SQL语句中的占位符绑定数据,如果预处理SQL语句不包含占位符,可省略此参数。演示如何使用预处理方法:9.1.5预处理机制<?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()); //输出结果:bool(true)2.数据绑定预处理SQL语句中有占位符时,使用execute()方法、bindParam()方法和bindValue()方法为占位符绑定数据。bindParam()方法和bindValue()方法的区别:bindParam()方法将占位符绑定到指定的变量名上,使用execute()方法执行预处理SQL语句时,只需要修改变量名的值。bindValue()方法将值绑定到占位符上,使用execute()方法执行预处理SQL语句时,每修改一次值,都需要重复执行一次bindValue()方法和execute()方法。9.1.5预处理机制(1)execute()方法execute()方法的参数$input_parameters是一个数组,该数组的元素个数必须与预处理SQL语句中的占位符数量相同。当占位符是问号占位符时,$input_parameters必须是一个索引数组;当占位符是参数占位符时,$input_parameters必须是一个关联数组。使用execute()方法为问号占位符绑定数据:<?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预处理机制使用execute()方法为参数占位符绑定数据:$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预处理机制为参数占位符绑定数据可以使用“:参数名”或“参数名”的形式(2)bindParam()方法使用bindParam()方法为问号占位符绑定数据时,bindParam()方法的第1个参数是一个以1开始的数字,表示对应预处理中的第几个问号占位符,使用bindParam()方法为参数占位符绑定数据时,bindParam()方法的第1个参数是“:参数名”或“参数名”的形式。使用bindParam()方法为问号占位符和参数占位符绑定数据://绑定问号占位符$stmt->bindParam(1,$name);$stmt->bindParam(2,$entry_date);//绑定参数占位符$stmt->bindParam(':参数名',$name);$stmt->bindParam('参数名',$entry_date);//省略“:”9.1.5预处理机制将占位符绑定指定的变量后,即可进行变量的赋值和预处理SQL语句的执行:list($name,$entry_date)=['Charles','2019-1-1'];$stmt->execute();list($name,$entry_date)=['Andy','2019-1-1'];$stmt->execute();9.1.5预处理机制(3)bindValue()方法bindValue()方法和bindParam()方法的第1个参数的使用方法相同,bindValue()方法的第2个参数用于传入一个值,它无须进行变量的绑定,使用较为方便。使用bindValue()方法为问号占位符和参数占位符绑定数据://绑定问号占位符$stmt->bindValue(1,'Charles');$stmt->bindValue(2,'2019-1-1');$stmt->execute();//绑定参数占位符$stmt->bindValue(':参数名','Charles');$stmt->bindValue('参数名','2019-1-1');//省略“:”$stmt->execute();9.1.5预处理机制

先定一个小目标!掌握PDO错误处理,能够使用不同的错误处理模式进行错误处理。9.1.6PDO错误处理在使用SQL语句操作数据库时,难免会出现各种各样的错误,如语法错误、逻辑错误等。为了避免SQL语句出现这些错误,我们既可以利用前面学习过的异常处理方式手动捕获PDOException类异常,也可以使用PDO提供的错误处理模式进行错误处理。9.1.6PDO错误处理PDO提供了3种错误处理模式:①PDO::ERRMODE_SILENT:此模式表示在发生错误时不进行任何操作,只简单地设置错误代码。通过PDO类的errorCode()方法和errorInfo()方法获取最后一次操作的错误码和错误信息。②PDO::ERRMODE_WARNING:此模式表示在发生错误时,将错误作为警告抛出,不中断程序的运行。③PDO::ERRMODE_EXCEPTION:此模式是默认的错误处理模式,它表示在错误发生时抛出相关异常。此模式在项目调试当中较为实用,可以快速地找到存在问题的代码。9.1.6PDO错误处理setAttribute()方法用于设置PDO的属性,在程序中使用该方法设置错误处理模式。语法格式PDO::setAttribute(PDO::ATTR_ERRMODE,$value);PDO::ATTR_ERRMODE表示设置错误处理模式,$value表示设为哪种错误处理模式,如PDO::ERRMODE_WARNING。9.1.6PDO错误处理演示如何设置WARNING错误处理模式:<?php$dsn='mysql:host=localhost;port=3306;dbname=myframe;charset=utf8mb4';$pdo=newPDO($dsn,'root','123456');//设置错误模式$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);//预处理SQL语句$stmt=$pdo->prepare('SELECT*FROM`test`');//执行预处理SQL语句,若execute()方法返回false表示执行失败if(false===$stmt->execute()){echo'错误码:'.$stmt->errorCode().'<br>'; //输出错误码

print_r($stmt->errorInfo()); //输出错误信息}9.1.6PDO错误处理上述代码运行结果:9.1.6PDO错误处理多学一招:PDO属性的获取PDO属性的获取使用PDO类提供的getAttribute()方法可以获取PDO连接的特定属性的值,用于查询和检索与数据库连接相关的各种属性。getAttribute()方法的语法格式:PDO::getAttribute($attribute);$attribute用于指定要获取的属性的常量值多学一招:PDO属性的获取PDO属性的获取getAttribute()方法中的常量值是PDO::ATTR_*系列常量中的一个,$attribute的可选值如下:PDO::ATTR_AUTOCOMMIT:连接的自动提交模式。PDO::ATTR_CASE:列名在结果集中的大小写方式。PDO::ATTR_CLIENT_VERSION:客户端库版本。PDO::ATTR_CONNECTION_STATUS:连接状态。PDO::ATTR_DRIVER_NAME:驱动程序名称。PDO::ATTR_SERVER_INFO:服务器信息。PDO::ATTR_SERVER_VERSION:数据库服务器版本。多学一招: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'驱动程序名称是'.$driver_name; //输出结果:驱动程序名称是mysql$server_version=$pdo->getAttribute(PDO::ATTR_SERVER_VERSION);echo'服务器的版本是'.$server_version; //输出结果:服务器的版本是8.0.32

先定一个小目标!掌握PDO事务处理,能够使用PDO类的事务处理的相关方法实现事务。9.1.7PDO事务处理PDO类提供了事务处理的相关方法:9.1.7PDO事务处理方法名说明PDO::beginTransaction()启动事务PDO::commit()提交事务PDO::inTransaction()检查是否在事务内PDO::rollBack()回滚事务演示如何进行事务处理:9.1.7PDO事务处理<?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(); //开启事务try{$stmt=$pdo->prepare('INSERTINTO`student`(`name`)VALUES(?)');

//执行插入操作

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

$pdo->rollBack(); //回滚事务echo'执行失败:'.$e->getMessage();}在自定义框架中封装数据库操作类9.2

先定一个小目标!掌握封装DB类的方法,能够在自定义框架中封装DB类。9.2.1【案例】封装DB类在自定义框

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论