PHP框架 - Laravel 5.6
一、composer安装
1.1 composer介绍
composer是php用来管理依赖关系的工具,你可以在自己的项目中申明所依赖的外部关系库,composer会帮你安装这些依赖的库文件;一句话,composer是一个工具,是为php项目准备的软件管家。
1.2 composer工作原理
1.3 composer安装
windows安装:下载Composer-Setup.exe,安装目录选择php对应版本的php.exe所在位置
命令行安装:
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
注意:如果是安装composer.exe文件,一定要安装在使用的版本的php的安装目录,也就是php.exe所在目录
1.4 镜像地址设置
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ 或者 composer config -g repo.packagist composer https://packagist.phpcomposer.com
镜像原理:
1.5 配置文件修改
①开启php.ini扩展配置:
extension=php_openssl.dll
extension=php_pdo_mysql.dll (PDO)
extension=php_mbstring.dll (mbstring)
extension=php_fileinfo.dll (验证码)
extension=php_curl.dll (请求发送)
②开启http.conf配置
LoadModule deflate_module modules/mod_deflate.so
LoadModule rewrite_module modules/mod_rewrite.so
1.6 使用composer更新composer
composer self-update
1.7 使用composer安装项目依赖
composer install :(项目第一次执行composer,没有composer.json文件)
它将会去读取你的composer.lock而非composer.json,并且以此为标准去下载依赖。
当你本地没有composer.lock的时候,它所做的事情和composer update其实并没有区别。
这意味着,只要你本地有一份composer.lock,你就可以保证无论过去了多久,你都能拉到相同的依赖。而如果你把它纳入你的项目的版本控制中,那么你就可以确保你项目中的每一个人、每一台电脑,不管什么系统,都能拉取到一模一样的依赖,以减少潜在的依赖对部署的影响。当然,请记得,你应该使用的命令是composer install。
composer update:(有composer.json文件之后)
当你执行update的时候,composer会去读取composer.json中指定的依赖,去分析他们,并且去拉取符合条件最新版本的依赖。然后他会把所拉取到的依赖放入vendor目录下,并且把所有拉取的依赖的精确版本号写入composer.lock文件中。
二、Laravel框架安装
2.1 安装具体版本命令
composer create-project laravel/laravel=5.6.* my_laravel --prefer-dist
laravel/laravel=5.6.* 这个* 代表这里安装5.6的最高版本
2.2 查看框架版本信息:php artisan --version
2.3 启动服务:php artisan serve
2.4 laravel框架目录结构
① app目录:项目的核心目录,主要用于存放项目核心代码,也包括控制器、模型
② bootstrap目录:laravel启动目录,引导框架并配置自动加载的文件,该目录还包含了一个 cache 目录,存放着框架生成的用来提升性能的文件,比如路由和服务缓存文件。
③ config目录:项目的配置目录,主要存放项目配置文件
④ database目录:数据填充和迁移文件
⑤ public目录:项目入口文件和系统静态资源目录(css、js、img)
⑥ resources目录:目录包含了语言包、视图和未编译的资源文件(如 LESS、SASS 或 JavaScript)
⑦ routes目录:目录包含了应用的所有路由定义,Laravel 默认包含了几个路由文件: web.php, api.php, console.php 和 channels.php。
⑧ storage目录:storage 目录包含编译的 Blade 模板、基于文件的会话和文件缓存、以及框架生成的其他文件。这个目录被细分成 app 、 framework 和 logs 三个子目录。 app 目录可以用来存储应用生成的任何文件。 framework 目录用来存储框架生成的文件和缓存。最后, logs 目录包含应用的日志文件。
总结:存放缓存文件和日志文件,在linux系统下,该目录需要有写权限
⑨ vendor目录:主要用于存放第三方类库文件,比如:邮件发送类文件、验证码类文件、laravel框架源码文件等等。
⑩ .env文件:设置系统相关环境信息文件(config目录里面的配置文件内容一般都是读取该文件里面的配置信息)
①① artisan脚手架文件
注意:使用artisan文件需要注意2点
a、 php必须添加环境变量,必须保证版本
b、 artisan必须存在命令行当前的工作路径下,也就是框架的根目录下
①② composer.json:依赖包配置文件
声明当前需要的软件依赖,不能删除,composer需要读取使用
2.5 laravel启动方式
① 方式1, 命令启动:php artisan serve 该启动方式不需要启动apache/nginx ,不推荐使用,能跑php,但是不启动数据库
② 方式2, 使用wamp环境,配置个虚拟主机
2.6 配置框架app key:php artisan key:generate
三、Laravel入门基础
3.1 laravel路由介绍
a、路由配置文件
b、路由定义
c、请求方式有哪些
d、路由参数
还可以通过?形式get传参:
路由别名:
获取路由列表命令(查看系统已有路由):php artisan route:list
e、路由群组
3.2 控制器使用
a、控制器文件写在哪里
b、控制器命名
大驼峰命名 + Controller.php
c、创建控制器
php artisan make:controller TestController 默认路径Controllers目录下
php artisan make:controller Admin/AdminController 指定路径,Controllers/Admin目录下
d、控制器路由
e、接收用户输入
① 使用Illuminate\Support\Facades\Input类,Input静态接收请求参数
Facades:门面思想。门面是一个介于类的实例化与没有实例化中间的一个状态,其实是类的一个接口实现。这个状态下可以不实例化类,但是可以调用类中的方法。说白了就是静态方法。
在laravel中如果需要使用facades,但又不想写那么长的引入操作,则可以在config/app.php中定义长串的别名(aliases数组中定义别名)。
② 使用 Illuminate\Http\Request类,Request依赖注入的方式获取输入参数
③ 使用Illuminate\Support\Facades\Request类,Request静态接收请求参数
3.3 DB类操作数据库
a、引入DB类文件
注意:使用DB类,需要use Illuminate\Support\Facades\DB类,DB门面类在app.php文件中已经定义了别名DB,可以直接use DB,不需要写太长的空间
b、新增数据
c、修改数据
d、查寻数据
//获取数据
public function getData(){
//1.获取所有数据
$db = DB::table('user');
$data1 = $db->get();
//var_dump($data1);
foreach ($data1 as $k=>$v){
//get查寻出来都是对象,不能再用访问数组的方式访问,必须访问对象方式访问数据
var_dump($v->name);
}
//2.大于...
$data2 = DB::table('user')->where('id','>',2)->get();
dump($data2);
//3.获取单行或列
$one = DB::table('user')->first(); //返回一个对象,相当于limit(1)
//$one = $db->where('name','菲兹')->first();
dump($one);
//4.获取某个具体的值
$data3 = DB::table('user')->where('id','=',3)->value('email');
dump($data3);
//5.获取某些字段的值
$data4 = DB::table('user')->select('name','age','email')->get();
dump($data4);
//6.分块查寻
echo '<hr/>';
DB::table('user')->orderBy('id')->chunk(1,function($user){
foreach ($user as $k=>$v){
dump($v);
}
});
}
e、排序操作
public function paixu(){
$db = DB::table('user');
$data1 = $db->orderBy('id','desc')->get();
dump($data1);
}
f、分页操作
public function fenye(){
$db = DB::table('user');
//limit:限制输出的条数
//offset:从什么地方开始
//组合起来等价于 limit 2,1
$data1 = $db->limit(2)->offset(1)->get();
dump($data1);
}
g、删除操作
public function delete(){
$db = DB::table('user');
$data1 = $db->where('id','<',3)->delete();
dd($data1); //返回删除数据的条数
}
h、执行任意的sql语句
public function doSql(){
//1.statement语句
$data1 = DB::statement("insert into user values(6,'卡莎',18,'kasha@163.com')");
var_dump($data1);
//2.select语句
$data2 = DB::select("select * from user");
dump($data2);
}
3.4 视图操作
a、视图写在哪里
视图可以进行分目录管理的
b、视图文件的命名与渲染
c、变量的分配与展示
public function assignVar(){
$date = date('Y-m-d H:i:s',time());
$day = '星期六';
//return view('article.list',['date'=>$date,'day'=>$day]);
return view('article.list')->with(['date'=>$date,'day'=>$day]);
}
d、compact()函数使用
compact函数使php内置函数,跟框架没有关系,主要作用用于打包数组,在当前的符号表中查找该变量名并将它添加到输出的数组中,变量名成为键名而变量的内容成为该键的值!!!
语法:compact('变量名1','变量名2',...)
e、在模板视图中使用函数
语法:{{函数名(参数1,参数2)}}
说明:函数可以是php内置的函数,也可以是laravel框架中定义的
f、循环与分支
g、模板继承
父级页面:
子级页面:
h、文件包含
语法:@include('模板文件名') 文件名不带后缀
i、外部文件引入
在laravel框架中,封装了一个asset()方法
注意:href = "{{asset('css/blog/')}}" asset()方法的参数可以是单级目录,也可以是多级目录
3.5 CSRF攻击
a、什么是csrf攻击
b、csrf使用
注意:有一种情况是没得选择的,只能使用csrf_token,就是使用ajax异步提交表单方式
区别:csrf_token只是输出了token值,csrf_field输出了整个input隐藏域
c、csrf验证中排除列外路由
action地址写法一:
action地址写法二:
3.6 模型操作(AR模式)
a、模型介绍
b、模型文件位置和模型文件创建
使用命令创建模型:php artisan make:model Admin\Article
c、定义模型
//定义模型关联的数据表
protected $table = 'user';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false; //数据表中没有created_at updated_at字段时必须禁用!!!
//设置允许写入的字段,使用create()方法的时候必须定义$fillable属性
protected $fillable = ['name','age','email'];
//设置不允许写入字段, $fillable 和 $guarded 只能二选一设置
//protected $guarded = ['price'];
d、在控制器中使用模型
use App\Admin\User; //在控制器中操作模型,use模型
方式①:AR模式
实例化模型,然后再去使用类,例如: $model = new User(); $model->get();
public function userAdd1(){
//1.实例化模型
$userModel = new User; //dd($userModel);
//2.给属性赋值,字段与类的属性映射
$userModel->name = Input::get('name');
$userModel->age = Input::get('age');
$userModel->email = Input::get('email');
$res = $userModel->save();
dd($res); //这种方式返回 bool 类型结果
}
注意:上面这种方法可以完成数据的插入,但是开发中不建议使用
方式②:
直接像使用DB门面一样的的操作,以调用静态方法为主的形式,该形势下模型不需要实例化,例如: User::get(); 等价于 DB::table('user')->get();
public function addForm(){
//1.加载静态页面视图
return view('admin.user.useradd2');
}
public function userAdd2(Request $request){
//2.使用User::create()方式写入数据,依赖注入的方式接收变量
$res = User::create($request->all());
//$data = Input::all();
//var_dump($data);
dd($res); //这种方式返回 obj 类型结果
}
注意:如果使用create()方法,则需要在模型中定义fillable属性 允许写入的字段,如果数据表中没有时间相关字段也需要禁用时间自动更新功能
e、查询操作
public function userList(){
//1.查寻单条指定id的数据
$res = User::find(9); //返回 obj
dump($res);
dump('姓名:'.$res->name.' 年龄:'.$res->age);
//2.查寻所有数据转成数组
$res3 = User::get()->toArray();
dump($res3);
//3.查寻符合条件的第一条数据
$res4 = User::where('id','>',6)->first()->toArray();
var_dump($res4);
//4.all()方法
$res5 = User::all(); //all()方法查询,不支持链接其他辅助查寻方法
dump($res5);
//5.get()方法获取某些字段
$res5 = User::where('id','>',12)->get(['id','name'])->toArray();
var_dump($res5);
echo '<br>';
//6.select()获取某些字段
$res6 = User::where('id','>',10)->select('id','name','age')->get()->toArray();
dump($res6);
}
f、修改数据
public function userEdit(){
//1.AR模式修改操作
$data = User::find(6);
dump($data); //obj
//给要修改的字段赋值
$data->email = 'aike@163.com';
//保存修改
$res1 = $data->save();
dump($res1);
//2.模型使用update方式更新数据
$res2 = User::where('id',6)->update(['email'=>'aike2@163.com']);
dump($res2); //int 1|0
}
g、删除数据
public function userDelete(){
//1.模型删除操作
$data = User::find(10);
$res1 = $data->delete();
var_dump($res1); //返回bool true|false
//2.DB类里面的方式删除
$res2 = User::where('id','>',14)->delete();
var_dump($res2); //int 返回受影响的行数
}
3.7 自动验证
a、自动验证介绍
b、演示浏览器禁用js功能
未禁用之前:
设置浏览器禁用js:
禁用以后:
注意:所以一个功能完善的应用,前后端都要做验证,不止单独的前端或者单独的后端单方面做验证!!!
c、获取/判断请求方式
public function userAdd3(Request $request){
//1.请求方式判断一
$method1 = $request->isMethod('POST'); //true
var_dump($method1);
//2.请求方式判断二
$method2 = request()->method(); //POST
var_dump($method2);
//3.请求方式判断三
$method3 = Input::method(); //POST
var_dump($method3);
//4.请求方式判断四
$method4 = Request::METHOD_POST; //POST
var_dump($method4);
$method5 = FacRequest::method(); //POST 静态Request的别名 FacRequest
var_dump($method5);
}
d、快速验证($this->validate验证)
注意:多个验证规则使用 "|" 字符进行隔开
语法:$this->validate(数据对象,数组形式的验证规则)
//1. 快速验证($this->>validate验证)
public function addForm3(){
//1.加载静态页面视图
return view('admin.user.useradd3');
}
public function uValidate(Request $request){
//使用场景,返回到模板中
if(Request::METHOD_POST == 'POST'){
$input = $this->validate($request,[
//验证规则
'name' => 'required|between:2,10|alpha_dash',
'age' => 'required|integer|between:18,100',
'email' => 'required|email|unique:user,email',
'tel' => 'required',
],[
'name.required' => '姓名必须填写',
'name.between' => '姓名2-10个字符',
'name.alpha_dash' => '姓名只能是字母、数字、破折号( - )以及下划线( _ )',
'age.required' => '年龄必须填写',
'age.integer' => '年龄请填写整数',
'age.between' => '年龄18-100岁之间',
'email.required' => '邮箱必须填写',
'email.email' => '邮箱格式不对',
'email.unique' => '邮箱已经存在',
'tel.required' => '手机号必须填写',
],[
'name' => '姓名',
'age' => '年龄',
'email' => '邮箱',
'tel' => '手机号',
]);
return ['msg'=>$input];
}else{
return ['code'=>100501,'msg'=>'请求方式错误'];
}
}
<body>
<form action="{{route('ad3')}}" method="post">
姓名:<input type="text" name="name" id=""><br/>
年龄:<input type="text" name="age" id=""><br/>
邮箱:<input type="text" name="email" id=""><br/>
<input type="hidden" name="_token" value="{{csrf_token()}}">
<input type="submit" value="提交">
</form>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
</body>
响应效果:
e、独立验证
use Validator;
//2.独立验证
public function addForm5(){
//1.加载静态页面视图
return view('admin.user.useradd5');
}
public function duliValidate(Request $request){
//使用场景,响应ajax
if($request->isMethod('POST')){
$validator = Validator::make($request->all(),[
'name' => 'required|between:2,10|alpha_dash',
'age' => 'required|integer|between:18,100',
'email' => 'required|email|unique:user,email',
'tel' => 'required',
],[
'name.required' => '姓名必须填写',
'name.between' => '姓名2-10个字符',
'name.alpha_dash' => '姓名只能是字母、数字、破折号( - )以及下划线( _ )',
'age.required' => '年龄必须填写',
'age.integer' => '年龄请填写整数',
'age.between' => '年龄18-100岁之间',
'email.required' => '邮箱必须填写',
'email.email' => '邮箱格式不对',
'email.unique' => '邮箱已经存在',
'tel.required' => '手机号必须填写',
],[
'name' => '姓名',
'age' => '年龄',
'email' => '邮箱',
'tel' => '手机号',
]);
//dump($validator);
//dump(get_class_methods($validator)); //获取类里面的所有方法
//如果有错误,返回true
if($validator->fails()){
return redirect()->back()->withErrors($validator);
}
}else{
return ['code'=>100501,'msg'=>'请求方式错误'];
}
}
f、表单验证(验证器验证)
创建表单验证类文件: php artisan make:request Admin/ArticleRequest
namespace App\Http\Requests\Admin;
//单个验证规则失败后停止验证所有规则
protected $stopOnFirstFailure = true;
/**
* 如果您打算在应用程序的其它部分处理请求的授权逻辑,只需从 authorize 方法返回 true
* @return bool
*/
public function authorize()
{
return true; //设置为true
}
/**
* 书写验证规则
* @return array
*/
public function rules()
{
return [
'name' => 'required|between:2,10|alpha_dash',
'age' => 'required|integer|min:18|max:100',
'email' => 'email|unique:user,email',
'tel' => [
'required',
'unique:user,tel',
'regex:/^1[3456789][\d]{9}$/'
],
'pwd' => 'required|alpha_dash|between:6,16|confirmed', //confirmed属性写在原始密码字段上
//'pwd_confirmation' => 'required|alpha_dash|same:pwd', //same,验证字段必须与给定字段匹配
'pwd_confirmation' => 'required|alpha_dash', //same 和 原始密码字段的confirmed有一个就行
'pic' => 'nullable|image|max:100', //laravel5.6bug,需要去修改允许上传的文件格式!!!
//'pic' => 'mimes:jpg,jpeg,png,gif,bmp,webp|max:100',
];
}
//自定义错误信息
public function messages()
{
return [
'name.required' => '姓名必须填写',
'name.between' => '姓名2-10个字符',
'name.alpha_dash' => '姓名只能是字母、数字、破折号( - )以及下划线( _ )组成',
'age.required' => '年龄必须填写',
'age.integer' => '年龄请填写整数',
'age.min' => '必须年满18岁',
'age.max' => '年龄不超过100岁',
//'email.required' => '邮箱必须填写',
'email.email' => '邮箱格式不对',
'email.unique' => '邮箱已经存在',
'tel.required' => '电话号码必须填写',
'tel.unique' => '电话号码已经存在',
'tel.regex' => '电话号码不正确',
'pwd.required' => '密码不能为空',
'pwd.between' => '密码6-16位字符',
'pwd.alpha_dash' => '密码只能是字母、数字、破折号( - )以及下划线( _ )组成',
'pwd_confirmation.required' => '确认密码不能为空',
'pwd_confirmation.alpha_dash' => '确认密码只能是字母、数字、破折号( - )以及下划线( _ )组成',
'pwd.confirmed' => '两次密码不一致',
//'pic.mimes' => '请上传jpeg,bmp,png,gif,jpg格式图片',
'pic.image' => '请上传jpg,jpeg,bmp,png,gif,webp格式图片',
'pic.max' => '上传图片大小不超过100kb',
];
}
use App\Http\Requests\Admin\User as UserValidate; //自定义表单验证
public function addForm4(){
//1.加载静态页面视图
return view('admin.user.useradd4');
}
//进行表单验证
public function zdyValidate(UserValidate $request){
//获取通过验证的数据
$valited = $request->validated();
//dump($valited); //array
//获取部分通过验证的数据
//$valited2 = $request->safe()->only(['name','email']);
//dd($valited2);
//调用写入数据库方法
$res = self::userAdd4($request);
if($res){
$data = ['code'=>100016,'msg'=>'添加成功'];
//设置setEncodingOptions(JSON_UNESCAPED_UNICODE),返回数据禁止Unicode编码
//return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
return response()->json($data);
}else{
$data = ['code'=>100015,'msg'=>'添加失败'];
return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
}
}
public function userAdd4(Request $request){
$salt = getRandomString($length = 15); //获取盐str
//密码加密
//$pass1 = Crypt::encrypt($request->input('pwd')); //一长串,188个字符
$pass = Hash::make($request->input('pwd').$salt); //60个字符
$data = $request->except(['pwd','pwd_confirmation']);
$data['pwd'] = $pass;
$data['salt'] = $salt;
return UserModel::create($data);
}
g、输出效果展示成中文:
① 语言包下载网址:https://packagist.org/,搜索laravel-lang,选择下载量最多、收藏最多的下载
② 下载包:
③ 查看文档:
④ laravel5-语言包安装命令:
在项目根目录下面执行语言包安装命令 composer require laravel-lang/lang:^3.0 或者 composer require laravel-lang/lang:^3.0 laravel-lang/publisher:^3.0
下载原始包文件位置:
⑤ 复制zh-CN文件夹到框架如下目录:
⑥ 修改laravel框架配置文件:config/app.php,修改 'locale' => 'en' 为 'locale' => 'zh-CN'
⑦ 测试效果
⑧ 修改语言包中错误,resources/lang/validation.php 中age字段, 'age' =>'年轻' 改为 'age' => '年龄'
⑨ 语言包中添加字段 ,resources/lang/validation.php 中添加tel字段测试
h、修改laravel框架返回数据,禁止Unicode编码
① return json数据的地方加上setEncodingOptions(JSON_UNESCAPED_UNICODE)
return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
② 修改文件: vendor\laravel\framework\src\Illuminate\Http\JsonResponse.php的构造函数,$this->encodingOptions = $options ; 修改为 $this->encodingOptions = JSON_UNESCAPED_UNICODE ;
public function __construct($data = null, $status = 200, $headers = [], $options = 0)
{
//$this->encodingOptions = $options;
$this->encodingOptions = JSON_UNESCAPED_UNICODE;
parent::__construct($data, $status, $headers);
}
i、laravel框架中添加公共函数
① 在app目录下面新建Helper\functions.php文件
② 配置composer
打开根目录下的composer,在autoload项下面按照图示配置
③ 执行composer命令
composer dump-auto
3.8 文件上传
a、表单方式上传
不考虑异步(js、ajax)上传,使用纯表单提交上传,需要注意点有以下:
① 表单type="file" ,提交方式 method 为post
② form表单具有enctype="multipart/form-data" 属性
multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思 ;默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。
③ 具备一个提交按钮,submit可以直接提交, button需要写js提交
注意:文件上传的核心 就是文件移动,move_upload_file()
b、超全局变量$_FILES
c、处理上传文件
//3.8 文件上传
//加载静态页面
public function fileView(){
return view('admin.user.files');
}
//处理文件上传
public function fileUpload(Request $request){
if($request->isMethod('POST')){
$file = $request->file('pic');
//$pic = $request->pic; 两个获取结果一样,都是Illuminate\Http\UploadedFile对象
//判断是否有上传文件 且 上传的文件是否有效
if($request->hasFile('pic') && $request->file('pic')->isValid()){
//获取文件的原始名称
dump($request->file('pic')->getClientOriginalName());
//获取文件扩展名
dump($request->file('pic')->getExtension());
//获取文件上传错误码,上传成功为0
dump($request->file('pic')->getError());
//获取文件 “原始后缀名”
dump($request->file('pic')->getClientOriginalExtension());
//获取文件mime类型
dump($request->file('pic')->getClientMimeType());
//获取文件上传的错误信息
dump($request->file('pic')->getErrorMessage());
//移动文件
$path = './uploads/avatar/'.date('Ymd',time());
$fileName = md5(time().rand(100000,999999)).'.'.$request->file('pic')->getClientOriginalExtension();
//返回 Symfony\Component\HttpFoundation\File\File 对象
$request->file('pic')->move($path,$fileName);
$data = $request->all();
$data['pic'] = date('Ymd',time()).'/'.$fileName;
//添加到数据库
UserModel::create($data);
}else{
$data = ['code'=>100012,'msg'=>'上传失败'];
return response()->json($data);
}
}else{
$data = ['code'=>100010,'msg'=>'请求方式错误'];
return response()->json($data);
}
}
d、laravel5.6框架图片验证bug修改
① 原因:上传jpeg、jpg后缀图片,提示请上传图片文件; png、gif后缀的图片文件能够验证通过
② 添加允许上传的文件后缀
a、找到文件位置:D:\xxx\la56\vendor\laravel\framework\src\Illuminate\Validation\Concerns
b、找到文件名:ValidatesAttributes.php
c、找到validateImage()方法,添加允许上传的文件格式
public function validateImage($attribute, $value)
{
return $this->validateMimes($attribute, $value, ['jpg','jpeg', 'png', 'gif', 'bmp', 'svg','webp']);
}
注意:多文件上传验证规则
e、封装一个文件上传函数
use Illuminate\Http\Request;
/**
* 多文件上传
* @param Request $request *请求对象
* @param $fieldName *表单字段名称
* @param $category *保存文件的分类文件夹名称
* @return array|\Illuminate\Http\JsonResponse
*/
function multiFileUpload($request,$fieldName = null,$category = null){
//$request->file($fieldName) array[obj] ,多图片上传的时候数据结构:数组里面是文件对象
if($request->hasFile($fieldName) && $request->file($fieldName)){
$result = [];
foreach($request->file($fieldName) as $file){
//移动文件
$path = './uploads/'.$category.'/'.date('Ymd',time());
$fileName = md5(time().rand(100000,999999)).'.'.$file->getClientOriginalExtension();
$file->move($path,$fileName);
$result[] = date('Ymd',time()).'/'.$fileName; //20190128/8df7306be.jpg
}
return $result;
}
}
3.9 数据分页
a、laravel分页简介
在laravel里面完成分页是很简单的,它的思想和其他框架有些不一样,其他一些框架使用的分页类完成的,laravel是直接调用模型的分页方法,返回对应的数据和分页字符串
b、分页类文件位置
c、模型用法
语法:{{$保存数据的对象->links()}}
public function paginate(){
//1. 没有分页的效果
$data1 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->get();
//2.简单分页效果
$data2 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->simplePaginate(10);
//3.分页效果
$data3 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->paginate(15);
foreach($data3 as $k=>$v){
$data3[$k]['pic'] = '/uploads/avatar/'.$v['pic'];
}
return view('admin.user.paginate',compact('data3'));
}
① 简单分页效果
② 普通分页效果
d、自定义分页视图效果
自定义分页视图的制作最简单的方法是使用 vendor:publish 命令将它们导出到 resources/views
/vendor 目录:
使用命令php artisan vendor:publish --tag=laravel-pagination 移动文件
编辑default.blade.php 和 bootstrap-4.blade.php 文件修改显示效果
3.10 验证码
a、安装验证码依赖包
包名:搜索 captcha
指定版本安装:composer require mews/captcha=3.0.2 这里安装mews/captcha 3.0.2版本
b、修改配置文件
config/app.php文件配置
① 注册提供商
//验证码服务提供者
Mews\Captcha\CaptchaServiceProvider::class,
② 配置aliases 键
'Captcha' => Mews\Captcha\Facades\Captcha::class,
c、自定义参数配置
使用命令生成配置文件:php artisan vendor:publish
'default' => [
'length' => 5,
'width' => 120,
'height' => 36,
'quality' => 90,
'math' => true,
//'expire' => 60,
],
d、实现验证码显示
返回URL:captcha_src() 返回图片:captcha() 返回HTML:captcha_img()
<img src="{{captcha_src()}}" alt="验证码" onclick="this.src=this.src+'?'+Math.random()">
e、验证码验证
'code' => 'required|captcha',
'code.required' => '验证码不能为空',
'code.captcha' => '验证码不正确',
3.11 数据表的迁移与填充
1、数据的迁移操作
a、介绍
迁移:创建数据表的操作 + 删除数据表的操作
填充:往数据表里面填充写入数据(数据的插入操作)
b、数据的迁移操作
在迁移过程中,操作可以分为两个部分:创建与编写迁移文件 执行迁移文件
迁移文件默认位置:
① 创建迁移文件
案例:创建一张表,假设数据表的名字叫做paper,迁移文件名:create_paper_table
创建的时候可以通过artisan命令来执行迁移文件的生成:php artisan make:migration 迁移文件名
/**
* Run the migrations.
*创建数据表
* @return void
*/
public function up()
{
Schema::create('paper', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*删除数据表
* @return void
*/
public function down()
{
Schema::dropIfExists('paper');
}
② 编写迁移文件代码
编写迁移代码,实现数据表的up方法和down方法,参考框架database\migrations\目录下原始的文件书写
案例要求:
$table表示整个表的实例,语法:$table->列类型方法('字段名',[长度/值范围])->列修饰方法();
public function up()
{
Schema::create('paper', function (Blueprint $table) {
$table->increments('id');
$table->string('paper_name',100)->notNull()->unique();
$table->tinyInteger('total_score',tinyint)->default(100);
$table->integer('start_time')->nullable();
$table->integer('duration');
$table->tinyInteger('status')->default(1);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('paper');
}
c、执行迁移文件
① 执行up方法(创建数据表)
第一次执行迁移文件,需要执行的命令:php artisan migrate:install 生成一张migrations表,如下:
执行命令:php artisan migrate 【执行迁移文件的,创建数据表】
② 执行down方法(删除数据表)
执行命令:php artisan migrate:rollback 【回滚最后一次的迁移操作,不会删除迁移文件】
注意:迁移文件的文件名不要做任何修改,要报错!!!
2、数据表填充器
填充操作就是往数据表中写测试数据的操作
a、填充器所在目录
b、创建填充器
使用命令:php artisan make:seeder 【建议写法:大写表名+TableSeeder】 如:PaperTableSeeder
class PaperTableSeeder extends Seeder
{
public function run()
{
//
}
}
c、编写填充器代码
注意:在填充器文件中可以使用DB门面去新增数据,但是需要注意,DB门面在使用的时候不需要用户再去引入,一旦引入则报错,可以直接使用
public function run()
{
DB::table('paper')->insert([
'paper_name' => '07年中考',
'total_score' => 558,
'start_time' => strtotime('+7 days'),
'duration' => 120,
'status' => 1
], [
'paper_name' => '13年高考',
'total_score' => 556,
'start_time' => strtotime('+7 days'),
'duration' => 120,
'status' => 1
]
);
}
d、执行填充器文件
使用命令:php artisan db:seed --class = 需要执行的种子文件名
php artisan db:seed --class=PaperTableSeeder
3.12 响应处理
在laravel框架中响应正常的情况有两种, 一是常规的直接响应,另外一个是ajax响应;其中展示视图和直接响应字符串都属于常规响应
1、 常规响应
return view('admin.user.lis');
return 'hello';
2、 ajax响应
① 常见的ajax响应数据类型
json、xml、text/html
案例:
a、发送请求
b、响应处理
//处理响应处理
public function ajaxResponse(Request $request){
if($request->isMethod('GET')){
$data = UserModel::get();
return response()->json($data); //响应给laravel框架的必须是字符串or对象
//return ['a'=>10,'b'=>100]; //转成obj了
}else{
$data = ['code'=>100010,'msg'=>'请求方式错误'];
return response()->json($data);
}
}
② 跳转响应(重定向)
语法:
return redirect('路由');
return redirect()->to('路由');
3.13 会话控制(记忆)
session默认存到文件中,session文件的目录:storage/framework/sessions
① 使用session
控制器中引用 use Illuminate\Support\Facades\Session, 由于session门面在app.php中已经定义好了别名,所以在控制器中可以直接use Session;
public function huihua(){
//1. 存储一个变量
Session::put('name','红家伙');
Session::put('age','19');
session_start();
dump($_SESSION); //这里原生获取不到
//2. 获取一个变量
echo Session::get('name').'<br>';
//3.获取一个默认值
echo Session::get('name2','那个.').'<br>';
echo Session::get('name6',function(){
return '就是她';
}).'<br>';
//4.获取所有session信息
dump(Session::all());
//5.检查某个session是否存在
dump(Session::has('name'));
//6. 删除一个session变量
dump(Session::forget('name'));
//删除session中全部变量
Session::flush();
dump(Session::all());
}
3.14 缓存操作
laravel为不同的缓存提供了统一的API,缓存配置位于config/cache.php。在该文件中指定使用哪个缓存,系统默认使用文件缓存,其缓存位置位于:storage/framework/cache/data
① 设置缓存
② 获取缓存
③ 删除缓存数据
④ 缓存数值的增加/减少
⑤ 获取并存储
public function huancun(){
//1.设置一个缓存,如果存在,则覆盖
Cache::put('name','那个人',100);
//2.设置一个缓存,存在同名则不添加
Cache::add('age','20',50);
Cache::add('mimi','200',1000000);
//3.永久存储
Cache::forever('sex','女');
//4.获取值
$value1 = Cache::get('name');
dump($value1);
//4.获取值,不存在则使用默认值
$value2 = Cache::get('sign',function(){
return '这个家伙很懒,什么都没留下';
});
dump($value2);
//5.检查缓存中是否存在某个值
if(Cache::has('sex')){
echo '存在值';
}else{
echo '不存在值';
}
//6.从缓存中获取缓存,然后删除
$value3 = Cache::pull('sex');
dump($value3);
dump(Cache::get('sex'));
//7.从缓存中移出缓存数据
$value4 = Cache::forget('age');
dump($value4); dump(Cache::get('age'));
//8.清除所有缓存,并且删除目录
//Cache::flush();
//9.缓存值增加/减少
Cache::increment('mimi',10);
Cache::decrement('mimi');
//10.设置一个默认时间
$time = Cache::remember('time',100,function(){
return date('Y-m-d H:i:s',time());
});
dump($time);
//11.永久存储
$day = Cache::rememberForever('timeforever',function(){
return date('Y-m-d',time());
});
dump($day);
}
3.15 中间件
中间件作为请求和响应的中间人,它是一种过滤机制类型。在laravel中通过中间件来进行后台用户是否登录的验证操作,防止后台用户翻墙操作。
a、创建中间件
php artisan make:middleware 中间件名
b、中间件所在目录
c、注册中间件
在laravel中,中间件有两种类型; 即全局中间件(不管是在前台还是在后台都执行)和路由中间件。全局中间件将在应用程序的每个HTTP请求运行,而路由中间件将被分配到一个特定的路由,中间件可在 模app\Http\Kernel.php 注册
该文件包含两个属性,$middleware 和 $routeMiddleware, $middleware属性用于注册全局中间件, $routeMiddleware用于注册路由指定中间件。
① 全局中间件
② 路由中间件 (直接路由中间件、路由分组中间件)
路由web.php中注册路由中间件
③ 特殊的一种,控制器中间件
3.16 联表查询
① 普通联表查询
数据来源:文章表、作者表
表1:文章表 t1 主表(跟在from关键词后面的表)
表2:作者表 t2 从表(跟在join关键词后面的表)
关联条件:文章表的author_id = 作者表的id
联表方式:左外连接
原始sql:select t1.id,t1.article_name,t2.author_name from article as t1 left join author as t2 on t1.author_id=t2.id;
public function lianbiao(){
$data = DB::table('article as t1')
->select('t1.id','t1.article_name','t2.author_name')
->leftJoin('author as t2','t1.author_id','=','t2.id')
->get();
dump($data);
}
3.17 模型关联
① 一对一关联关系
例如:一篇文章只有一个作者
a、创建模型
b、定义模型代码
class Article extends Model
{
//定义模型关联的数据表
protected $table = 'article';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false;
}
class Author extends Model
{
//定义模型关联的数据表
protected $table = 'author';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false;
}
c、关联模型的关联方法
注意:在写关联模型的时候要分析出谁关联谁,谁做主动关联的模型。 当前案例:文章关联作者,文章是主模型,需要关联代码写在主模型中
//模型关联操作:关联作者模型(一对一)
//语法
public function 被关联的模型名小写(){
return $this->hasOne('需要关联模型的命名空间','被关联模型的关系字段','本模型中的关系字段');
}
public function author(){
return $this->hasOne('App\Admin\Author','id','author_id');
}
关联关系的使用方法:使用动态属性进行调用
案例:通过模型关联的一对一关系查询出每篇文章对应的作者名称
//1.一对一
public function oneOnOne(){
$data = \App\Admin\Article::get(); //$data Illuminate\Database\Eloquent\Collection 对象
foreach($data as $key=>$value){ //$value Article模型对象
echo '文章编号是:'.$value->id.'; '.'文章名称是:'.$value->article_name.'; '.'文章作者是:
'.$value->author->author_name.'<br>';
}
}
注意:使用模型一对一关联关系之后,其可以替代之前写的join联表操作
② 一对多关联关系
例如:一篇文章有多条评论
a、创建评论表:
b、创建评论模型:
class Comment extends Model
{
//定义模型关联的数据表
protected $table = 'comment';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false;
}
c、关联模型的关联方法:文章模型(主) 、评论模型(从)
需求:查询出每篇文章下所有的评论
//语法
public function 被关联的模型名小写(){
return $this->hasMany('需要关联模型的命名空间','被关联模型的关系字段','本模型中的关系字段');
}
public function comment(){
return $this->hasMany('App\Admin\Comment','art_id','id');
}
//2.一对多
public function oneToMore(){
//查询数据
$data = \App\Admin\Article::get(); //$data Illuminate\Database\Eloquent\Collection 对象
foreach ($data as $key=>$value){ //$value App\Admin\Article模型对象
echo '文章编号:'.$value->id.'; '.'文章名称是:'.$value->article_name.'; '.'其下评论有:<br>';
//$value->comment 这里的comment是模型里面的方法!!!
foreach ($value->comment as $k=>$v){ //$v App\Admin\Comment 模型对象
echo ' '.$v->comment.'<br>'; //comment是字段!!!
}
}
}
效果:
③ 多对多关联关系
例如:一篇文章可能有多个关键词,一个关键词可能被多篇文章使用
a、建表:已经存在文章表,还需要关键词表、关键词和文章的关系表
b、创建模型:
注意:根据手册中记录的语法要求,不需要给关系表单独的创建模型
class Keyword extends Model
{
//定义模型关联的数据表
protected $table = 'keyword';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false;
}
c、查询每篇文章下的关键词
//语法
public function 被关联的模型名小写(){
return $this->belongsToMany('需要关联模型的命名空间','多对多模型的关系表名',
'当前模型的关系键','被关联模型的关系键');
}
注意:根据案例需求,此处的关系映射依旧写在文章模型中
//3.多对多
public function moreToMore(){
$data = \App\Admin\Article::get(); //$data Illuminate\Database\Eloquent\Collection 对象
//循环输出
foreach($data as $key=>$value){ //$value App\Admin\Article模型对象
echo '文章编号:'.$value->id.'; '.'文章名称是:'.$value->article_name.'; '.'其所用的关键词有:<br>';
//$value->keyword 这里的keyword是模型里面的方法!!!
//输出全部的关键词
foreach($value->keyword as $k=>$v){ //$v App\Admin\Keyword模型对象
echo ' '.$v->keyword.'<br>'; //keyword是字段!!!
}
}
}
效果:
3.18 项目初始化
① 下载框架
② 创建数据库,修改.env文件,配置数据库连接操作
③ 设置网站本地化为中文
a、下载语言包
b、复制下载的语言包到网站resources/lang/目录下面
c、修改配置文件config/app.php
④ 设置时区
⑤ 清理项目(删除不需要的文件)
a、删除app/Http/Controllers/Auth目录,项目中自定义登录逻辑
b、删除database/migrations/目录下面自带的数据迁移文件
c、删除database/seeds 目录下面的默认填充器文件
d、删除resources/views 目录下的welcome.blade.php文件
e、public目录下面的css、js文件也可以删除
⑥ 关闭mysql严格模式
编辑config/database.php 文件,将strict 由true修改为false
严格模式功能说明:
不支持对not null 字段插入null值
不支持对自增字段插入 '' 值
不支持text字段有默认值
⑦ 安装debugbar工具(开发的时候可选,线上别安装)
条件:php版本>=7.0,.env环境需要设置APP_DEBUG=true !!!
a、安装
composer require barryvdh/laravel-debugbar:~v3.3.0
b、修改配置文件config/app.php
Barryvdh\Debugbar\ServiceProvider::class,
'Debugbar' => Barryvdh\Debugbar\Facades\Debugbar::class,
效果:
3.19 其他总结
① 自定义code和msg
a、在app目录下创建common\SystemCode.php SystemMessage.php文件
interface SystemCode{
/*
|--------------------------------------------------------------------------
| 网络请求类code
|--------------------------------------------------------------------------
|100 + 1xx 格式,如:100101
*/
const REQ_METHOD_ERRCODE = 100101;
const REQ_PARAM_ERRCODE = 100102;
const NO_PRIVILEGE_CODE = 100103;
const TOKEN_EXPIRE_CODE = 100104;
const FORBIDDEN_CODE = 100105;
}
/**
* 接口提示信息类
*/
interface SystemMessage{
const REQ_METHOD_ERR = '请求方式错误';
const REQ_PARAM_ERR = '请求参数错误';
const NO_PRIVILEGE = '没有权限';
const TOKEN_EXPIRE = '登录已过期';
const FORBIDDEN = '服务器拒绝请求';
}
b、在控制器中使用code和msg
public function adminList(Request $request){
if($request->isMethod('GET')){
return view('admin.admin.adminlist');
}else{
$data = [];
$param = ['code'=>SystemCode::REQ_METHOD_ERRCODE,'msg'=>SystemMessage::REQ_METHOD_ERR,'data'=>$data];
return response()->json($param);
}
}
② laravel框架使用ajax post方式删除数据
②.① meta标签方式
a、在meta标签中添加csrf_token字段和值
<meta name="csrf-token" content="{{ csrf_token() }}">
b、删除按钮
<button type="button" class="btn btn-danger btn-md" onclick="del(this,{{$prilist->id}});">删除</button>
c、确保ajax发送之前添加X-CSRF-TOKEN
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
d、发起服务器请求
②.② ajax 的data属性值里面传递
③ laravel框架ajax提交数据,验证错误消息返回抛出提示