1、 PHP第7章 Laravel框架(上)初识Laravel路由控制器数据库操作视图防御CSRF攻击模型自动验证PHP网站开发实例教程 学习目标掌握了解熟悉掌握掌握了解Laravel框架13熟悉Laravel框架对CSRF攻击的处理方式掌握Laravel框架中路由的使用方法5掌握Laravel框架中对控制器、模型、视图的定义和使用方法24掌握Laravel框架的数据库操作和自动验证的使用方法 目录点击查看本节相关知识点点击查看本节相关知识点路由7.27.27.17.1初识Laravel7.37.3控制器点击查看本小节知识架构数据库操作7.47.4点击查看本小节知识架构 目录点击查看本节相关知识点
2、点击查看本节相关知识点防御CSRF攻击7.67.67.57.5视图7.77.7模型点击查看本小节知识架构自动验证7.87.8点击查看本小节知识架构 知识架构7.1 初识初识Laravel1Laravel概述2创建Laravel项目3配置VS Code编辑器4Laravel目录结构 知识架构7.2 路由路由1配置路由2路由参数3路由别名4路由分组 知识架构7.3 控制器控制器1创建控制器2控制器路由3接收用户输入 知识架构7.4 数据库操作数据库操作1配置数据库2添加数据3修改数据4查询数据5删除数据6执行SQL语句 知识架构7.5 视图视图1创建视图文件2向视图传递数据3视图数据的处理4循环操
3、作 知识架构7.5 视图视图5判断操作6模板继承7模板包含 知识架构7.6 防御防御CSRF攻击攻击1什么是CSRF攻击2在Laravel中防御CSRF攻击3从CSRF验证中排除例外路由 知识架构7.7 模型模型1定义模型2在控制器中使用模型3使用模型添加数据4使用模型查询数据5使用模型修改数据6使用模型删除数据 知识架构7.8 自动验证自动验证1如何进行自动验证2在Ajax请求中使用自动验证 7.1 初识Laravel Laravel概述Laravel是一套简洁、优雅的Web应用框架,具有富于表达性且简洁的语法,提供了强大的工具来开发大型应用,这些工具包括自动验证、路由、Session、缓存
4、、数据库迁移、单元测试等 7.1 初识Laravel Laravel概述Laravel框架具有目前大部分框架都具有的共同特点:l 单入口。为了让框架统一管理所有的请求,整个项目对外只提供一个入口l MVC开发模式。利用MVC可以更好地协同开发,为后期的维护提供方便l ORM(对象关系映射)方式操作数据库,支持AR(活动记录)模式 7.1 初识Laravel 创建Laravel项目步骤:l 开启常用扩展l 开启重写l 配置虚拟主机l 安装Laravel 7.1 初识Laravel 创建Laravel项目extension=curlextension=fileinfoextension=gd2ex
5、tension=mbstringextension=opensslextension=pdo_mysql开启常用扩展:7.1 初识Laravel 创建Laravel项目 DocumentRoot C:/web/www/laravel/public ServerName www.laravel.test ServerAlias laravel.testOptions-indexes AllowOverride All Require all granted配置虚拟主机:7.1 初识Laravel 创建Laravel项目composer create-project laravel/laravel
6、=5.5.*-prefer-dist./安装Laravel:7.1 初识Laravel 创建Laravel项目安装结果:7.1 初识Laravel 创建Laravel项目访问http:/www.laravel.test,页面显示结果:7.1 初识Laravel 配置VS Code编辑器使用VS Code编辑器打开Laravel项目,创建.vscode/settings.json文件,添加配置对代码进行语法检查和自动格式化 php.suggest.basic:false,php.executablePath:C:/web/php7.2/php.exe,phpcs.standard:psr2,fi
7、les.eol:n 7.1 初识Laravel Laravel目录结构Laravel一级目录的作用:目录目录作用作用app应用目录,保存项目中的控制器、模型等bootstrap和框架的启动相关的文件config存放一些配置文件database数据库迁移文件及数据填充文件public应用入口文件index.php和前端资源文件(如CSS、JavaScript等)resources存放视图文件、语言包和未编译的前端资源文件routes存放应用中定义的所有路由storage存放编译后的模板、Session文件、缓存文件、日志文件等tests自动化测试文件vendor存放通过Composer加载的依赖
8、 7.1 初识Laravel Laravel目录结构Laravel常用的子目录和文件:类型类型路径路径作用作用目录appHttp存放HTTP请求相关的文件目录appHttpControllers存放控制器文件目录appHttpControllersAuthAuth模块的控制器目录文件appHttpControllersController.php控制器的基类文件目录appHttpMiddleware中间件目录文件appUser.phpUser模型文件文件bootstrapautoload.php自动加载文件文件configapp.php全局配置文件 7.1 初识Laravel Laravel目
9、录结构Laravel常用的子目录和文件:类型类型路径路径作用作用文件configauth.phpAuth模块的配置文件文件configdatabase.php数据库配置文件文件configfilesystem.php文件系统的配置文件目录databasefactories存放工厂模式的数据填充文件目录databasemigrations存放数据库迁移文件目录databaseseeds存放数据填充器文件目录resourceslang存放语言包文件目录resourcesviews存放视图文件 7.1 初识Laravel Laravel目录结构Laravel常用的子目录和文件:类型类型路径路径作用作
10、用文件routesweb.php定义路由的文件目录storageapp存放用户上传的文件目录storageframework存放与框架自身相关的文件目录storagelogs存放日志文件文件publicindex.php入口文件文件.env环境变量配置文件文件artisan脚手架文件文件composer.jsonComposer依赖包配置文件 7.2 路由 配置路由路由需要在routes/web.php文件中进行配置,Route类定义路由的方式:Route:get(/hello,function()return hello;);/同时匹配get和post请求方式Route:match(get,
11、post,test1,function()return 通过match()匹配;);/匹配任意请求方式Route:any(test2,function()return 通过any()匹配;);7.2 路由 路由参数Laravel允许在请求URI中传递一些动态的参数,称为路由参数路由参数分为必选参数和可选参数,必选参数的语法为“参数名”可选参数的语法为“参数名?”演示如何使用必选参数:Route:get(find/id,function($id)return 输入的id为.$id;);7.2 路由 路由参数演示如何使用可选参数:Route:get(find2/id?,function($id=0
12、)return 输入的id为.$id;);7.2 路由 路由别名路由别名用来在路由定义的时候,为路由起一个别名演示给路由设置别名:Route:get(/hello/123,function()return hello;)-name(hello);7.2 路由 路由分组为了方便路由的管理,对路由进行分组,分组后可以对一组路由统一进行管理例如下面一组路由:/admin/login/admin/logout/admin/index/admin/user/add/admin/user/del 7.2 路由 路由分组路由分组后:Route:group(prefix=admin,function()Rou
13、te:get(login,function()return 这里是/admin/login;);Route:get(logout,function()return 这里是/admin/logout;);Route:get(user/add,function()return 这里是/admin/user/add;););7.3 控制器 创建控制器一个控制器文件应包含命名空间的声明和引入,以及控制器类的定义为了防止出错Laravel提供了自动生成控制器的命令php artisan make:controller 控制器名 7.3 控制器 创建控制器代码演示使用php artisan创建一个Test
14、Controller控制器:php artisan make:controller TestController 7.3 控制器 创建控制器Test控制器代码如下所示:?php namespace AppHttpControllers;use IlluminateHttpRequest;class TestController extends Controller /7.3 控制器 控制器路由控制器路由是路由的一种定义方式控制器路由是将回调函数修改为“控制器类名方法名”Route:get(admin/test1,AdminTestControllertest1);7.3 控制器 接收用户输入接
15、收用户输入的方式主要有两种:l 通过Request实例接收l 通过路由参数接收 7.3 控制器 接收用户输入通过Request实例接收用户输入:input(name);return name的值为.$name;7.3 控制器 接收用户输入使用Request实例接收查询字符串:1.给input()方法定义路由Route:get(test/input,TestControllerinput);2.访问http:/www.laravel.test/test/input?name=xiaoming输出结果:“name的值为xiaoming”7.3 控制器 接收用户输入使用Request实例接收路由参数
16、:1.修改路由定义方式,在路由中匹配name参数Route:get(test/input/name,TestControllerinput);2.修改input()方法3.访问http:/www.laravel.test/test/input?name=xiaoming输出结果:“name的值为xiaoming”public function input(Request$request)$name=$request-name;return name的值为.$name;7.3 控制器 接收用户输入通过路由参数接收用户输入:1.修改路由定义方式,在路由中匹配name参数Route:get(test
17、/input/name,TestControllerinput);2.修改input()方法3.访问http:/www.laravel.test/test/input?name=xiaoming输出结果:“name的值为xiaoming”public function input(Request$request)return name的值为.$name;7.4 数据库操作 配置数据库步骤:l 创建Laravel数据库,在数据库中创建member表l 在configdatabase.php文件中将配置参数从环境变量中获取l 在.env文件中配置数据库的参数l 在test控制器中创建方法,测试DB
18、类 7.4 数据库操作 添加数据insert()方法返回值为true或false,表示是否添加成功$data=name=tom,age=22,email=tomlaravel.test;dump(DB:table(member)-insert($data);7.4 数据库操作 添加数据insertGetId()方法返回值为自动增长的id$data=name=tom,age=22,email=tomlaravel.test;dump(DB:table(member)-insertGetId($data);7.4 数据库操作 修改数据update()方法用来修改指定的字段/将表中所有记录的name
19、字段的值都改为tom$data=name=tom;dump(DB:table(member)-update($data);7.4 数据库操作 修改数据increment()方法用来对数字进行递增/将表中所有记录的age字段的值都加1dump(DB:table(member)-increment(age);/将表中所有记录的member字段的值都加5dump(DB:table(member)-increment(age,5);7.4 数据库操作 修改数据decrement()方法用来对数字进行递减/将表中所有记录的member字段的值都减1dump(DB:table(member)-decrem
20、ent(age);/将表中所有记录的member字段的值都减5dump(DB:table(member)-decrement(age,5);7.4 数据库操作 修改数据使用WHERE条件限定要操作的记录/参数形式1:where(字段名,运算符,字段值)DB:table(member)-where(id,=,1)-update($data);/参数形式2:where(字段名,字段值),使用“=”运算符DB:table(member)-where(id,1)-update($data);/参数形式3:where(字段名=字段值),使用=运算符,支持多个字段,AND关系DB:table(member
21、)-where(id=1)-update($data);/where()表示AND,即“WHERE id=1 AND name=tom”DB:table(member)-where(id=1)-where(name=tom)-/orWhere()表示OR,即“WHERE id=1 OR name=tom”DB:table(member)-where(id=1)-orWhere(name=tom)7.4 数据库操作 查询数据查询多行数据:$data=DB:table(member)-get();foreach($data as$v)echo$v-id.-.$v-name.;7.4 数据库操作 查
22、询数据查询单行数据:/查询id为1的记录$data=DB:table(member)-where(id,1)-first();/输出id字段的值dump($data-id);7.4 数据库操作 查询数据查询指定字段的值:/获取name和email两个字段,返回多条记录$data=DB:table(member)-get(name,email);/获取name和email两个字段,返回一条记录$data=DB:table(member)-first(name,email);7.4 数据库操作 查询数据查询某个字段的值:/查询id为1的记录,返回name字段的值$name=DB:table(mem
23、ber)-where(id,1)-value(name);7.4 数据库操作 查询数据排序:$data=DB:table(member)-orderBy(age,desc)-get();7.4 数据库操作 查询数据分页:$data=DB:table(member)-limit(3)-offset(2)-get();7.4 数据库操作 删除数据第1种方式使用delete()方法删除指定的记录第2种方式使用truncate()方法清空整个数据表/删除id为1的记录,返回值为删除的行数$res=DB:table(member)-where(id,delete();/清空数据表(相当于SQL中的“TR
24、UNCATE member”)DB:table(member)-truncate();7.4 数据库操作 执行SQL语句通过DB类直接执行一些复杂SQL语句/执行SELECT语句,返回结果集$data=DB:select(SELECT*FROM member);/执行INSERT语句,返回true或falseDB:insert(INSERT INTO member SET name=tom);/执行UPDATE语句,返回受影响的行数DB:update(UPDATE member SET name=tim WHERE id=1);/执行DELETE语句,返回受影响的行数DB:delete(DEL
25、ETE FROM member WHERE id=1);/执行其他语句,如CREATE TABLE,返回true或falseDB:statement(CREATE TABLE test(id INT);7.5 视图 创建视图文件l 视图文件保存在resourcesviews目录中l 视图文件的名称以“.blade.php”或“.php”结尾l 当以“.blade.php”结尾,表示使用Blade模板引擎,在视图中可以使用模板语法和PHP原生语法l 当以“.php”结尾,表示不使用模板引擎,只能使用PHP原生语法 7.5 视图 创建视图文件演示视图文件的使用:创建resourcesviewssh
26、ow.blade.php文件 Document 当前显示的视图文件是show.blade.php 7.5 视图 创建视图文件演示视图文件的使用:在控制器中加载视图文件public function show()/加载视图文件resourcesviewsshow.blade.php return view(show);7.5 视图 创建视图文件演示视图文件的使用:浏览器访问测试运行结果 7.5 视图 创建视图文件view()函数的使用:对应的视图文件路径为resourcesviewhometestshow.blade.phpreturn view(home/test/show);/写法1,用“/
27、”分隔return view(home.test.show);/写法2,用“.”分隔 7.5 视图 向视图传递数据在视图文件中不能直接访问控制器中的变量,需要在控制器中为视图传递数据使用view()函数或with()函数为视图传递数据/方式1:通过view()的第2个参数传数据return view(模板文件,数组);/方式2:通过with()传数据return view(模板文件)-with(数组);/方式3:通过连续调用with()传数据return view(模板文件)-with(名称,值)-with(名称,值)7.5 视图 视图数据的处理特殊字符转义:Blade模板引擎在输出字符串时,
28、会自动进行HTML特殊字符的转义如果禁止Blade自动转义,在变量输出时使用“!$content!”7.5 视图 视图数据的处理通过函数对数据进行处理:在视图中输出数据时,可以通过函数来对数据进行处理例如,向视图传入一个时间戳数据,在视图中使用date()函数进行格式化处理 当前时间是:date(Y-m-d H:i:s,$time)7.5 视图 循环操作使用“foreach”模板语法来实现循环输出数组语法格式:foreach($variable as$key=$value)/循环体foreach 7.5 视图 循环操作代码演示“foreach”语法的使用:循环操作 foreach($data
29、as$v)$v-id -$v-name endforeach 7.5 视图 循环操作使用“if”模板语法进行判断操作语法格式:if(条件表达式1)/语句1elseif(条件表达式2)/语句2elseif(条件表达式3)/语句3else /以上条件都不满足时执行的语句endif 7.5 视图 模板继承将一个完整页面中的公共部分放在父页面中将不同的部分放在不同的子页面中子页面可以继承父页面来获得完整的页面 7.5 视图 模板继承子页面继承父页面语法:extends(需要继承的父页面)section(区块名称)区块内容endsection 7.5 视图 模板包含把多个页面中相同的部分抽取到子页面中,
30、通过include()将公共部分包含进来,得到完整的页面。7.6 防御CSRF攻击 什么是CSRF攻击CSRF(Cross-Site Request Forgery,跨站请求伪造)是互联网中常见的一种攻击方式它出现的原因是,当用户在网站中登录以后,网站无法判断其接下来收到的请求是用户主动发起的,还是被其他网站的恶意程序伪造的。当用户访问了其他网站时,其他网站可以伪造一个请求,发给这个已登录的网站,造成用户在不知情的情况下执行了发帖子、删除文章、转账之类的操作 7.6 防御CSRF攻击 什么是CSRF攻击GET方式的CSRF攻击当用户浏览了包含img标签的页面时,删除数据的操作在用户不知情的情况
31、下就被执行了。7.6 防御CSRF攻击 什么是CSRF攻击POST方式的CSRF攻击 document.getElementById(f).submit();当用户浏览了包含表单的页面时,删除数据的操作就已经静默执行了。7.6 防御CSRF攻击 在Laravel中防御CSRF攻击Laravel框架会对POST方式发过来的请求进行令牌验证,因此对安全性要求高的操作(如添加、修改、删除数据),应使用POST方式对GET方式不会进行令牌验证,因此而对安全性没有要求的操作(如查询),可以使用GET方式 7.6 防御CSRF攻击 在Laravel中防御CSRF攻击POST方式的请求通常使用表单进行发送,
32、在视图文件中编写表单的时候,可以通过模板语法“csrf_field()”或“csrf_token()”来获取令牌,将令牌放入表单中,随表单一起提交,这样就可以通过CSRF验证 7.6 防御CSRF攻击 在Laravel中防御CSRF攻击 收款人:转账金额:csrf_field()表单提交的POST请求,推荐使用 csrf_field()7.6 防御CSRF攻击 在Laravel中防御CSRF攻击$.ajax(url:route(trans),type:POST,headers:X-CSRF-TOKEN:csrf_token(),data:,scccess:function(res)consol
33、e.log(res););Ajax提交的POST请求,推荐使用 csrf_token()7.6 防御CSRF攻击 从CSRF验证中排除例外的路由l 并不是所有的请求都需要防御CSRF攻击l 例如为客户端(微信小程序、手机应用)提供接口时,不需要CSRF验证l 在appHttpMiddlewareVerifyCsrfToken.php文件中添加要排除的路由l 如果希望所有的路由都不进行验证,可以用“*”来表示 7.7 模型 定义模型使用php artisan命令可以自动创建一个模型php artisan make:model 模型名 7.7 模型 定义模型代码演示使用php artisan创建一
34、个Member模型:php artisan make:model Member 7.7 模型 定义模型Member模型代码如下所示:get();7.7 模型 使用模型添加数据save()方法的使用方式:先实例化模型,为模型的属性赋值,模型的属性对应数据表中字段,赋值完成后,调用save()方法进行保存$member=new Member();$member-name=save;$member-age=20;dump($member-save();/保存数据dump($member-id);/获取自动增长id 7.7 模型 使用模型添加数据fill()方法的使用方式:先在模型类中定义允许填充的字
35、段,以数组的方式为模型填充数据,数组的键名对应字段名/定义允许填充的字段protected$fillable=name,age,email;/fill()方法的使用$data=name=fill,age=20;$member=new Member();$member-fill($data);$member-save();7.7 模型 使用模型添加数据create()方法的使用方式:先在模型类中定义允许填充的字段,在实例化模型的同时,为模型填充数据/定义允许填充的字段protected$fillable=name,age,email;/create()方法的使用$data=name=tom,ag
36、e=20;$member=Member:create($data);$member-save();7.7 模型 使用模型查询数据find()方法根据主键查询记录/查询主键为4的记录,返回模型对象$member=Member:find(4);dump($member-name);/获取name字段的值dump($member-toArray();/将模型对象转换为数组/添加查询条件,返回name和age字段$member=Member:where(name,tom)-select(name,age)-find(1);/查询主键为1、2、3的记录,返回对象集合$members=Member:fin
37、d(1,2,3);7.7 模型 使用模型查询数据get()方法返回查询结果是对象集合$members=Member:where(id,1)-get();dump(get_class($members0);/输出结果:AppMember 7.7 模型 使用模型查询数据all()方法查询表中所有记录,返回模型对象集合/查询所有记录,返回对象集合$members=Member:all();/查询所有记录的name和age字段,返回对象集合$members=Member:all(name,age);7.7 模型 使用模型修改数据先查询后保存数据:$member=Member:find(5);if($m
38、ember)$member-name=test;$member-email=testlaravel.test;$member-save()else dump(修改失败:记录不存在);7.7 模型 使用模型修改数据直接修改数据:Member:where(id,7)-update(name=test,age=30);7.7 模型 使用模型删除数据先查询后删除数据:$member=Member:find(5);if($member)$member-delete()else dump(删除失败:记录不存在);7.7 模型 使用模型删除数据直接删除数据:$data=Member:where(id,8)-
39、delete();7.8 自动验证 如何进行自动验证自动验证示例代码:public function save(Request$request)$this-validate($request,/验证的字段名=规则1|规则2|规则3 name=required|min:2|max:20|unique:member,age=required|integer|min:1|max:120,email=required|email );/执行到此处表示验证通过 return 表单提交成功。;7.8 自动验证 如何进行自动验证Laravel中常见的验证规则:l required:表示该字段不能省略l mi
40、n和max:表示验证字符串的长度或者数字的大小,取决于验证的字段的数据类型。min表示最小值,max表示最大值l unique:用于验证其值在某个表中是否唯一,防止出现重复值l integer:用于验证该字段是不是一个整数l email:用于验证邮箱格式 7.8 自动验证 如何进行自动验证设置自定义的中文错误信息:$this-validate($request,name=required|min:2|max:20|unique:member,age=required|integer|min:1|max:120,email=required|email,name.required=用户名不能为空
41、,name.min=用户名最少2个字符,name.max=用户名最多20个字符,name.unique=用户名已存在,请换一个,age.required=年龄不能为空,age.integer=年龄必须是整数,age.min=年龄最小值为1,age.max=年龄最大值为120,email.required=邮箱不能为空,email.email=邮箱格式有误);7.8 自动验证 在Ajax请求中使用自动验证发送Ajax请求:$.ajax(url:/test/save,type:POST,headers:X-CSRF-TOKEN:csrf_token(),data:,success:function(data)console.log(JSON.parse(data););7.8 自动验证 在Ajax请求中使用自动验证在浏览器的控制台中可以看到服务器的验证结果