做开发有个原则是永远不能信任用户输入的数据;
即便前端已经做了验证;
在后端 php 也必须要再次验证;
laravel 为表单验证提供了强大且简单的方案;
创建示例路由:
routes/web.php
Route::prefix('validation')->group(function () { Route::get('create', 'ValidationController@create'); Route::post('store', 'ValidationController@store'); Route::get('edit', 'ValidationController@edit'); Route::post('update', 'ValidationController@update');});
PHP
创建控制器
php artisan make:controller ValidationController --resource
Bash
app/Http/Controllers/ValidationController.php
public function create(){ return view('validation.create');}
PHP
创建视图;
这里直接把官方自带的注册页面复制过来做示例了;
为了方便验证后台我把 html 标签的验证删除了;
并增加了一个 tag 选项;
resources/views/validation/create.blade.php
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">注册</div> <div class="panel-body"> <form class="form-horizontal" method="POST" action="{{ url('validation/store') }}"> {{ csrf_field() }} <div class="form-group{{ $errors->has('tag') ? ' has-error' : '' }}"> <label class="col-md-4 control-label">标签</label> <div class="col-md-6"> <select class="form-control" name="tag"> <option value="">请选择标签</option> <option value="1">1</option> <option value="2">2</option> </select> @if ($errors->has('tag')) <span class="help-block"> <strong>{{ $errors->first('tag') }}</strong> </span> @endif </div> </div> <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}"> <label for="name" class="col-md-4 control-label">用户名</label> <div class="col-md-6"> <input id="name" type="text" class="form-control" name="name" value="{{ old('name') }}" autofocus> @if ($errors->has('name')) <span class="help-block"> <strong>{{ $errors->first('name') }}</strong> </span> @endif </div> </div> <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}"> <label for="email" class="col-md-4 control-label">邮箱</label> <div class="col-md-6"> <input id="text" type="email" class="form-control" name="email" value="{{ old('email') }}"> @if ($errors->has('email')) <span class="help-block"> <strong>{{ $errors->first('email') }}</strong> </span> @endif </div> </div> <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}"> <label for="password" class="col-md-4 control-label">密码</label> <div class="col-md-6"> <input id="password" type="text" class="form-control" name="password"> @if ($errors->has('password')) <span class="help-block"> <strong>{{ $errors->first('password') }}</strong> </span> @endif </div> </div> <div class="form-group"> <label for="password-confirm" class="col-md-4 control-label">确认密码</label> <div class="col-md-6"> <input id="password-confirm" type="text" class="form-control" name="password_confirmation"> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <button type="submit" class="btn btn-primary"> 注册 </button> </div> </div> </form> </div> </div> </div> </div> </div>@endsection
HTML
现在到了后台验证的时候了;
laravel 可以直接在控制器中直接写验证逻辑;
不过我建议单独创建验证类;
以控制器名为目录;
以方法名为文件名;
这里为 store 方法创建一个验证类;
php artisan make:request Validation/Store
Bash
执行命令会生成 app/Http/Requests/Validation/Store.php 文件;
<?phpnamespace App\Http\Requests\Validation;use Illuminate\Foundation\Http\FormRequest;class Store extends FormRequest{ /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return false; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ // ]; }}
PHP
默认生成的验证类中只有 authorize
和 rules
方法;authorize()
主要用于验证权限;
如上面代码所示默认直接返回 fase
意味着所有的请求都不能通过验证;
假如说只允许 user_id
为 1 的用户执行 store
方法;
我们可以这样改写 验证类的 authorize()
;
public function authorize(){ return Auth::id() === 1 ? true : false;}
PHP
还有很多时候我们并不需要验证身份;
那直接返回 true
即可;
public function authorize(){ return true;}
PHP
另外就是 rules
方法;
根据前端页面增加以下验证;
public function rules(){ return [ 'tag' => 'required', 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ];}
PHP
这些规则都可以在文档中找到表单验证 ;
要使用这个验证器也很简单;
只需要在 store
方法的类型约束中使用 Store
即可;
use App\Http\Requests\Validation\Store;public function store(Store $request){ dump($request->all());}
PHP
增加验证后我们访问 /validation/create
页面点击注册按钮;
当点击注册按钮的时候会刷新下页面并显示红色的提示信息;
但是提示信息全是英文;
要想显示中文我们可以翻译 resources/lang/en/validation.php 文件中的内容;
另外 overtrue 有一个翻译好的扩展包可以供我们使用 laravel-lang ;
composer require "overtrue/laravel-lang:~3.0"
Bash
在 config/app.php 文件中把 Illuminate\Translation\TranslationServiceProvider::class,
替换成 Overtrue\LaravelLang\TranslationServiceProvider::class,
;
再次点击注册按钮就可以看到中文的提示信息了;
但是我们可以看到 tag
并没有被翻译出来;
像这类非通用性的字段;
我们可以在验证类 app/Http/Requests/Validation/Store.php 中定义 attributes
方法;
在方法中以键值对的方式翻译字段;
public function attributes(){ return [ 'tag' => '标签', ];}
PHP
标签是翻译过来了;
但是我明明一个下拉选择标签但是提示却是输入类型的不能为空;
叔可以忍婶婶是忍不了了;
像这类情况我们还可以在验证类 app/Http/Requests/Validation/Store.php 中定义一个 messages
方法;
在方法中以字段拼接验证类型来翻译字段和验证类型的错误信息;
public function messages(){ return [ 'tag.required' => '必须选择标签', ];}
PHP
泼飞克特;
终于如愿以偿;
验证失败的信息都是在 session 中存储;
可以使用 session()
获取到失败的信息;
另外 laravel 还在 app/Http/Kernel.php 中注册了 ShareErrorsFromSession
中间件;
它的作用是可以让我们在视图文件直接使用储存了错误信息的变量 $errors
;