目录
一、文件上传
在laravel, 里面实现文件的上传是很简单的,压根不用引入第三方的类库,作者把上传作为一个简单的http请求看待的。使用时可以参考手册。
(1)修改表结构,添加一个字段。用于存储头像的路径
ALTER TABLE `mydb`.`member` ADD COLUMN `avatar` varchar(100) NOT NULL AFTER `email`;
(2)创建添加数据的表单和路由
添加路由:/test10
创建展示视图的方法并且展示视图
回顾:要想表单能够上传(此处不考虑异步方式),则表单应该具备哪些要求?
答:
a.具有form标签,method必须为post, 必须具备enctype属性;
b.至少有一个input类型为file类型;
C.得具备一个提交按钮;
<form action="/test10" method="POST" enctype="multipart/form-data">
@csrf
<p>姓名:<input type="text" name="name" value="{{old('name')}}"></p>
<p>年龄:<input type="text" name="age" value="{{old('age')}}"></p>
<p>邮箱:<input type="email" name="email" value="{{old('email')}}"></p>
<p>头像:<input type="file" name="avatar" value="{{old('avatar')}}"></p>
<input type="submit">
</form>
(3)在控制器中,添加上传业务处理逻辑
获取上传的文件
可以使用Illuminate\Http\Request 实例提供的file方法或者动态属性来访问上传文件,file方法返回illuminate\Http\UploadedFile类的一个实例,该类继承自PHP标准库中提供与文件交互方法的SplFileInfo类
$file = $request->file('photo'); //通过file方法 来访问上传文件
$file = $request->photo; //通过动态属性 来访问上传文件
你可以使用hasfile 方法判断文件在请求中是否存在:
if ($request->hasFile('photo')){}
验证文件是否上传成功
使用isValid方法判断文件在上传过程中是否出错:if($request->file('photo')->isValid()){}
关于上传错误状态码error的取值: 0-7, 但是没有5,0表示成功。
问题:请你说出文件上传的本质(核心思想) ? 文件的移动,move_upload_file()
思路:
a.先去判断文件是否正常和存在
b.获取相关的信息(可选)
c.保存文件(其实就是移动文件到新的目录)
(4)创建上传文件的保存路径
在public目录中新建文件夹uploads
注意⚠️:这里需要给予uploads写权限,执行sudo chmod -R 777 uploads,才可以写入文件
关于项目中使用路径的说明:
如果路径是给php代码使用的,则路径建议使用“./”形式;如果路径是给浏览器使用的则建议使用“/”形式。
这里的相对路径是相对于public/index.php文件
(5)注意:如果使用的是create方法添加数据到数据表中,则这里还要修改一下模型里面的一个fllable属性,代表允许插入到数据库的字段
完整代码:
public function test10(Request $request)
{
if ($request->method() == 'POST') {
if ($request->hasFile('avatar') && $request->file('avatar')->isValid()) {
// 获取文件的原始名称
var_dump($request->file('avatar')->getClientOriginalName());
// 获取文件的大小
var_dump($request->file('avatar')->getSize());
// 获取文件后缀
var_dump($request->file('avatar')->getClientOriginalExtension());
var_dump($request->file('avatar')->extension());
// 文件移动(核心)
$path = md5(time() . rand(100000, 999999)) . '.' . $request->file('avatar')->extension();
$request->file('avatar')->move('./uploads', $path);
// 除了move也可以使用storeAs('文件夹名称')或store('文件夹名称')在laravel8默认存到storage/app下面了
// 获取全部的数据
$data = $request->all();
// 将路径添加到数组中
$data['avatar'] = './uploads/' . $path;
Member::create($data);
// dd($data); //调试代码
}
} else {
return view('test10');
}
}
如果上传出现了错误,一定要使用获取错误信息的方法getErrorMessage()
二、数据分页
在laravel里面要完成分页是很简单的,它的思想与之前的框架有些不一样,之前框架使用的是分页类完成分页,laravel是直接调用模型的分页方法,返回对应的数据和分页的字符串。
分页类的在框架中的位置(了解),在vendor/laravel/framework/src/illuminate/Pageination/Paginator.php
案例:使用分页功能实现当前member数据表的分页效果。
回忆/问题:分页效果的实现大致需要哪几个步骤才能实现?
a.查询符合分页条件的总的记录数
b.计算总的页数(总记录数/每页记录数,并且向上取整)
c.拼凑分页的连接
d.(核心)使用limit语法来限制每页的记录数
e.展示分页的页码和分页数据
f.如果可以,建议去考虑下分页的样式显示问题
1.创建路由
2.编写控制器中的方法代码,实现没有分页的效果(先不考虑分页效果)
3.展示数据
<table style="border:1px solid #ccc">
<thead>
<tr>
<th>id</th>
<th>名字</th>
<th>年龄</th>
<th>邮箱</th>
<th>头像</th>
</tr>
</thead>
<tbody>
@foreach($data as $val)
<tr>
<td>{{$val->id}}</td>
<td>{{$val->name}}</td>
<td>{{$val->age}}</td>
<td>{{$val->email}}</td>
<td><img style="width: 100px;height:100px;" src="{{ltrim($val->avatar,'.')}}" alt="头像"></td>
</tr>
@endforeach
</tbody>
</table>
public function test11(){
// 查询数据
$data = Member::get();
// 展示视图并且传递数据
return view('test11', compact('data'));
}
案例:使用分页展示上述的页面
要求:每页显示一条记录。
在laravel中分页有2个提供者: DB查询构建器,另外可以使用模型来实现。用法基本一致。
分页的基本语法:
Model::paginate(每页显示的记录数) 同样,paginate和get一样,支持使用where,orderBy等辅助查询的方法。
展示分页链接:
{{$保存数据的对象 -> links()}} 生成页码的链接
【可选】将页面的提示“>>”和“<<”改成 上一页 和 下一页 提示文字
直接改源码文件:vendor/laravel/framework/src/illuminate/Pageination/resources/views/default.blade.php
注意:可以使用simplePaginate()表示简单分页,只有上一页和下一页,没有分页字符串。
例如:$info = Member::orderby('age','desc')->simplePaginate(2);
附:分页数据对象的其他实用方法如下
分页数据对象->count() //当前页数据条数
分页数据对象->currentPage() //当前页码
分页数据对象->firstltem() //当前页第一条数据的序号
分页数据对象->hasMorePages() //是否有后续页码
分页数据对象->lastltem() //当前页最后一条数据的序号:
分页数据对象->lastPage() //最后页序号
分页数据对象->nextPageUrl() // 下一页的链接地址
分页数据对象->perPage() //每页显示数据条数
分页数据对象->previousPageUrl() //上一页的链接地址
分页数据对象->total() //记录总条数
分页数据对象->url(5) //制作指定页码的链接地址
三、验证码
1、验证码依赖安装
去packagist网站搜索验证码的代码依赖,关键词:CAPTCHA
地址:https://packagist.org/packages/mews/captcha#3.2.6
环境要求:php>=7.2,需要开启GD库
composer安装命令 #composer require mews/captcha
修改配置文件:config/app.php
找到'providers'=>这个键,添加一行信息Mews\Captcha\CaptchaServiceProvider::class,
配置别名aliases键,添加一个别名记录'Captcha' => Mews\Captcha\Facades\Captcha::class,
如果(可选)需要定义自己的配置,则需要生成配置文件:
$ php artisan vendor:publish
执行后可以在config目录中找到配置文件captcha.php,默认只生成4个,可以修改配置文件改成需要的个数,背景颜色等
2、案例
Return Image
captcha(); or Captcha::create();
Return URL
captcha_src(); or Captcha::src('default');
Return HTML
captcha_img(); or Captcha::img();
这里使用 captcha_src();
@if(count($errors)>0)
<div>
<ul>
@foreach($errors->all() as $error)
<li>{{$error}}</li>
@endforeach
</ul>
</div>
@endif
<form action="" method="POST">
@csrf
<p>姓名:<input type="text" name="name" value="{{old('name')}}"></p>
<p>年龄:<input type="text" name="age" value="{{old('age')}}"></p>
<p>邮箱:<input type="email" name="email" value="{{old('email')}}"></p>
<p>验证码:<input type="text" name="captcha" value="{{old('captcha')}}"><img src="{{captcha_src()}}" alt="验证码"></p>
<input type="submit">
</form>
验证码的验证操作
public function test12(Request $request)
{
// 判断请求类型
if ($request->method() == 'POST') {
$this->validate($request, [
//具体的规则
//字段 => 验证规则1|验证规则2|...
'name' => 'required|min:2|max:20',
'age' => 'required|integer|min:1|max:100',
'email' => 'required|email',
'captcha' => 'required|captcha' //captcha这个规则是第三方提供的规则
]);
echo '123123';
} else {
// 展示视图
return view('test12');
}
}
解决翻译问题
所以修改resources/lang/zh_CN/validation.php文件,添加两行翻译
四、数据表的迁移与填充
迁移:创建数据表的操作+删除数据表的操作
填充:往数据表里填充写入测试的数据(数据的插入操作)
1、数据的迁移操作
在迁移过程中,操作可以分为两个部分:创建与编写迁移文件、执行迁移文件。
1 迁移文件的创建与编写
迁移文件默认的位置:database/migrations
已经存在的2个文件,如果不打算使用系统自带的认证模块的话需要删除掉。
1.1创建迁移文件
案例:需要创建试卷的数据表,假设数据表的名字叫做paper。迁移文件名:create_paper_table
创建的时候可以通过自动代码生成工具artisan命令,执行生成迁移文件。
#php artisan make:migration 迁移文件名 Create a new migration file
#php artisan make:migration create_paper_table
里面有两个方法,up()方法表示创建数据库表的方法,down()方法表示删除数据表的方法
1.2编写迁移文件代码,让其能够实现数据表的创建(up 方法)与删除(down方法)
在写之前,可以参考项目初始化提供的user迁移文件:
Schema门面(类)是用于操作数据表的门面,调用其具体的方法之后就可以实现创建数据表与删除数据表,语法如上。照搬上述语法实现试卷表paper的创建:
试卷表的字段分析:
Id 表的主键,自增
Papef_ name 试卷名称,唯一,varchar(100), 不为空
Total_score 试卷总分,整型数字,tinyint, 默认为100
Start _time 试卷开始考试时间,时间戳类型(整型int)
Duration 考试时间长度,单位分钟,整型tinyint
Status 试卷是否启用的状态,1表示启用,2表示禁用,默认为1,tinyint
在创建数据表的列的时候遵循语法:
$table 表示整个表的实例
语法: $table -> 列类型方法(字段名,[长度/值范围]) -> 列修饰方法([修饰的值]);
列类型方法的作用:指定列的名称并且设置列的类型长度或者其值范围
修饰方法:主要是补充列的一些特征,例如有些列不能为空,或者有默认值等等
创建数据表的迁移代码:
public function up()
{
Schema::create('paper', function (Blueprint $table) {
// 每个列的定义代码
// $table -> 列类型方法(字段名,[长度/值范围]) -> 列修饰方法([修饰的值]);
// 自增的主键id
$table->increments('id');
// 试卷名称,唯一,varchar(100),不为空
$table->string('paper_name', '100')->unique();
// 试卷总分,整型数字,tinyint,默认为100
$table->tinyInteger('total_score')->default(100);
// 试卷开始考试时间,时间戳类型(整型int)
$table->integer('start_time')->nullable();
// 考试时间长度,单位分钟,整型tinyint
$table->tinyInteger('duration');
// 试卷是否启用的状态,1表示启用,2表示禁用,默认为1,tinyint
$table->tinyInteger('status')->default(1);
});
}
删除数据表的迁移代码:
public function down()
{
Schema::dropIfExists('paper');
}
1.2执行迁移文件
执行分为up执行和down执行
Up方法的执行:
如果在当前的项目中第一次执行迁移文件的话,则需要先去执行:
#php artisan migrate:install
作用:用于创建记录迁移文件的记录数据表。
需要执行up方法,则需要执行命令:(注意:需要删除系统自带的迁移文件,只保留自己的)
#php artisan migrate //执行迁移文件的:创建数据表
down方法执行:(回滚操作,删除数据表)
#php artisan migrate:rollback //回滚最后一次的迁移操作,回滚操作不删除迁移文件
回滚操作只删除迁移表中的记录和对应的数据表,其他操作不执行。
注意:删除(回滚)之后会删除上一个批次的迁移记录,并且同批次建立的数据表也会删除,但是迁移文件依旧存在,方便后期继续迁移(创建数据表)。
针对迁移文件名的提示:如果迁移文件已经创建好并且执行了,就不要去修改迁移文件的名称,容易出错的。
2、数据表填充器
填充操作就是往数据表中写测试数据的操作。
2.1填充器(种子文件)的创建与编写
1.填充器默认的所在目录
database/seeders
2.创建填充器
#php artisan make:seeder 填充器名称 约定俗成的写法:大写表名+TableSeeder
例如:以paper表为例,则名称应该为PaperTableSeeder
需要给storage目录权限#sudo chmod -R 777 storage
#php artisan make:seeder PaperTableSeeder
创建好的种子文件:PaperTableSeeder.php
3.【重点】编写填充器的代码,实现往数据表中写入数据
注意:在填充器文件中可以使用DB门面去新增数据,但是需要注意,DB门面在使用的时候需要用户自己引入,可以直接使用。
use Illuminate\Support\Facades\DB;
class PaperTableSeeder extends Seeder
{
public function run()
{
// 定义数组
$data = [
[
'paper_name' => '五年高考,三年模拟',
'start_time' => strtotime('+7 days'),
'duration' => '120',
],
[
'paper_name' => '黄冈密卷',
'start_time' => strtotime('+7 days'),
'duration' => '120',
],
[
'paper_name' => '衡水中学期中考试卷',
'start_time' => strtotime('+7 days'),
'duration' => '120',
],
];
// 写入数据
DB::table('paper')->insert($data);
}
}
2.2执行填充器文件
命令:#php artisan db:seed --class=需要执行的种子文件名(不带.php)
种子文件不像迁移文件,迁移操作有单独的对应关系表去记录,由于种子文件的执行没有任何的记录,所以在执行种子文件的时候需要指定需要执行的种子文件。
#php artisan db:seed --class=PaperTableSeeder
填充器的执行操作没有回滚一说,没有删除。如果需要回滚,则可以手动清空对应的数据表。
五、项目初始化(使用laravel做项目)
1、创建laravel项目
确定项目站点位置:
通过composer进行创建:#composer create-project laravel/laravel --prefer-dist ./
2、建立数据库
创建数据库
修改.env文件,配置数据库的连接操作
3、设置网站本地化为中文
修改语言包的配置:
下载语言包:#composer require laravel-lang/lang
复制vendor/laravel-lang/lang/locales/zh_CN到resources/lang
修改config/app.php文件中的配置项locale:
4、设置项目使用的时区
修改默认的时区,config/app.php文件中的配置项timezone
配置项的值:Asia/shanghai Asia/chongqing PRC
5、清理项目(删除不需要的文件)
删除app/Http/Controllers/Auth目录,因为需要自定义登录逻辑,这是默认自带的
删除database/migrations/* 的默认的迁移文件
删除database/seeders
删除resource/views/welcome.blade.php
在Public目录下的js、css 文件夹也可以进行删除:
6、关闭MySQL的严格模式(可选)
编辑 config/ database.php将 strict由true修改为 false
严格模式的功能说明
不支持对 not null 字段插入nul值
不支持对自增长字段插入''值
不支持text字段有默认值
7、安装debugbar工具条(可选)
地址:https://packagist.org/packages/barryvdh/laravel-debugbar
安装命令:composer require barryvdh/laravel-debugbar --dev
最后修改config/app.php文件进行配置provider和aliases数组
启动测试一下:#php artisan serve
装好之后的效果(在页面的左下角会有一个按钮,可以点击,点击之后展开即可):
六、响应处理
在laravel中,响应正常情况下有2个类型:常规的直接响应,另外一个是ajax的响应。
其中展示视图以及直接响应字符串都属于常规的响应。
例如:常规的响应
展示视图:
return view('welcome');
直接返回某个字符串:
return 'hello world';
1. ajax请求的响应
常见的ajax响应数据类型:json和xml、text/html
案例:在页面中输出一个按钮,按钮要可以被点击,点击之后发送ajax请求,请求后台的数据,后台返回前端ajax一个json的数据(不要使用json_encode函数)
1.1创建路由
1.2创建两个方法,其中一个负责展示,另一个负责响应ajax
1.3创建视图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script>
$(function() {
$('#btn').click(function() {
$.get('/test14', function(data) {
console.log(data);
}, 'json');
});
});
</script>
</head>
<body>
<button id="btn">点击我</button>
</body>
</html>
1.4点击按钮之后能够产生一个ajax请求【重点】
发送ajax请求:在jQuery中你知道发送ajax请求的方式有几种?4种
$.get : $.get(地址,[参数对象,回调,期望返回类型]);
$.post : $.post(地址,[参数对象,回调,期望返回类型]);
$.ajax : $.ajax(obj); 参数只有一个,就是参数的对象
$.getJSON : $.getJSON(地址,[参数对象,回调]); 该方法一般用于解决跨域请求
请分辨以下四种是不是跨域
http://baidu.com
https://baidu.com 跨域,协议不一样
http://baidu.com:80
http://baidu.com:443 跨域
http://baidu.com/abc
http://baidu.com/XYZ 不跨域
http://a.baidu.com
http://b.baidu.com 跨域
1.5处理响应【重点】
在laravel中框架如果需要响应json数据,则写成语法:
return response()->json(需要json输出的数据);
现在也可以直接 return $data; //$data可以是数组,也可以是对象
public function test14()
{
// 查询数据
$data = Member::all();
// json格式响应
// return json_encode($data);
// return response()->json($data);
return $data;
}
补充:在laravel中布尔值是不能被直接通过return响应输出的
2. 跳转响应(重定向)
在有一些页面,例如同步添加操作,完成操作之后不能停留在当前页面,最好做一个跳转操作,也就是需要一个跳转的响应。
以之前的“上传操作代码”为例:后续比较理想的情况应该是在处理完成之后需要一个跳转提示,告知用户是否成功,成功则应该返回上一页,失败则应该输出错误提示。
两个跳转方式任选一个:
return redirect(路由); 该参数的路由可以是完整的请求路由,也可以是通过route方法+别名获取的路由
return redirect()->to(路由);
产生了302响应进行跳转