一、前言
- 有读者建议我出一个 Lumen 的 自定义表单验证 示例
实际上,官方文档已经很描述得非常详细了。阅读本文的前提是你已经对 Laravel 的 验证 和 本地化 有所掌握
二、开始
因为 Lumen 已经是精简版的缘故,所以框架本身并没有对 表单验证 做过多的处理
默认的,如果沿用 Laravel 中的validator()
方法验证错误的表单,将会抛出一个Illuminate\Validation\ValidationException
的异常:<?php
# Illuminate\Validation\Validator.php
public function validate()
{
if ($this->fails()) {
throw new ValidationException($this);
}
return $this->validated();
}
既然框架已经抛出异常了,那么我们只要去捕获此类异常,然后根据自定义的格式输出接口,改变原有的渲染方式即可
<?php
# App\Exceptions\Handler.php
public function render($request, Exception $exception)
{
// 拦截表单验证的异常
if ($exception instanceof ValidationException) {
$errors = $exception->errors();
$message = '';
// 此处错误信息 $msg 会根据 APP_LOCAL 格式化成自定义的内容
foreach ($errors as $key => $msg) {
$message .= ($key . ' => ' . implode(' | ', $msg) . ' && ');
}
return response()->json([
'code' => 4000,
'message' => rtrim($message, ' && '),
'errors' => $errors
]);
} elseif ($exception instanceof ServerException) { // 拦截自定义服务端的异常
return response()->json([
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
]);
}
return parent::render($request, $exception);
}
三、详解
对于复杂的表单提交,如果是在 Laravel 中,通常是去实现一个自定义的请求类:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserEditRequest 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 [
'mobile' => 'required|cn_mobile', // cn_mobile 是自定义的验证规则,表示只支持国内手机号
'email' => 'required|email',
'name' => 'required|size:6,12'
];
}
}
但是由于 Lumen 已经精简掉了
Illuminate\Foundation\Http\FormRequest
这个类, 所以就没有办法沿用这种方式了
那么换一种思路呢?实际上我们在 中间件 中去处理请求,也是能达到相同的效果:<?php
namespace App\Http\Middleware;
use App\Exceptions\ServerException;
use App\Http\Form\Contract AS FormContract;
use Closure;
class Form
{
public function handle($request, Closure $next, $v)
{
$class = app('App\\Http\\Form\\' . ucfirst($v));
if ($class instanceof FormContract) {
$class->handle($request);
} else {
throw new ServerException(5000);
}
return $next($request);
}
}
在 Lumen 中定义好 中间件 后,可以在需要启用表单验证的地方调用即可,例如在任意 控制器 的
__constructor()
方法处使用:<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class User extends Controller
{
public function __construct()
{
# 表示只对 edit + create 方法使用 form 中间件
# form:user 同时也指定了表单验证类 App\Http\Form\User.php
$this->middleware('form:user', ['only' => ['edit', 'create']]);
}
public function index()
{
$user = [
'name' => 'AdamTyn',
'email' => 'tynadam@foxmail.com',
'mobile' => '1888888888',
];
return response()->json([
'data' => $user,
'code' => 0
]);
}
public function edit(Request $request)
{
// do somethings
return response()->json($request->all());
}
public function create(Request $request)
{
// do somethings
return response()->json($request->all());
}
}
对于更多的表单,则可以在
App\Http\Form
命名空间下继续创建对应的 表单验证类,具体实现可以通过示例 Code 去进一步了解
经过上述一顿操作之后,可以在浏览器熟练地输入对应路由地址,即可看到:{
"code": 4000,
"message": "mobile => 手机号为必传参数. && email => email不能为空. && name => name不能为空.",
"errors": {
"mobile": [
"手机号为必传参数."
],
"email": [
"email不能为空."
],
"name": [
"name不能为空."
]
}
}
眼尖的读者应该发现 (当然我也在前文的注释中悄悄地提及了),我们的错误信息不再只是英文,而是已经出现了更为具体的中文描述了
还记得 前言 中提到的 本地化 吗?也即框架的Illuminate\Validation\ValidationException
的异常信息都是会根据设置的语言进行格式化的,默认是使用英语。感兴趣的读者可以自行查看resources/lang
目录:
最后放出参考的示例 Code
四、结语
本教程面向新手,更多教程会在日后给出。
- 随着系统升级,软件更新,以后的配置可能有所变化,在下会第一时间测试并且更新教程。
- 欢迎联系在下,讨论建议都可以,之后会发布其它的教程。