一、前言

  1. 有读者建议我出一个 Lumen自定义表单验证 示例
  2. 实际上,官方文档已经很描述得非常详细了。阅读本文的前提是你已经对 Laravel验证本地化 有所掌握

    二、开始

  3. 因为 Lumen 已经是精简版的缘故,所以框架本身并没有对 表单验证 做过多的处理
    默认的,如果沿用 Laravel 中的 validator() 方法验证错误的表单,将会抛出一个 Illuminate\Validation\ValidationException 的异常:

    1. <?php
    2. # Illuminate\Validation\Validator.php
    3. public function validate()
    4. {
    5. if ($this->fails()) {
    6. throw new ValidationException($this);
    7. }
    8. return $this->validated();
    9. }
  4. 既然框架已经抛出异常了,那么我们只要去捕获此类异常,然后根据自定义的格式输出接口,改变原有的渲染方式即可

    1. <?php
    2. # App\Exceptions\Handler.php
    3. public function render($request, Exception $exception)
    4. {
    5. // 拦截表单验证的异常
    6. if ($exception instanceof ValidationException) {
    7. $errors = $exception->errors();
    8. $message = '';
    9. // 此处错误信息 $msg 会根据 APP_LOCAL 格式化成自定义的内容
    10. foreach ($errors as $key => $msg) {
    11. $message .= ($key . ' => ' . implode(' | ', $msg) . ' && ');
    12. }
    13. return response()->json([
    14. 'code' => 4000,
    15. 'message' => rtrim($message, ' && '),
    16. 'errors' => $errors
    17. ]);
    18. } elseif ($exception instanceof ServerException) { // 拦截自定义服务端的异常
    19. return response()->json([
    20. 'code' => $exception->getCode(),
    21. 'message' => $exception->getMessage(),
    22. ]);
    23. }
    24. return parent::render($request, $exception);
    25. }

    三、详解

  5. 对于复杂的表单提交,如果是在 Laravel 中,通常是去实现一个自定义的请求类:

    1. <?php
    2. namespace App\Http\Requests;
    3. use Illuminate\Foundation\Http\FormRequest;
    4. class UserEditRequest extends FormRequest
    5. {
    6. /**
    7. * Determine if the user is authorized to make this request.
    8. *
    9. * @return bool
    10. */
    11. public function authorize()
    12. {
    13. return false;
    14. }
    15. /**
    16. * Get the validation rules that apply to the request.
    17. *
    18. * @return array
    19. */
    20. public function rules()
    21. {
    22. return [
    23. 'mobile' => 'required|cn_mobile', // cn_mobile 是自定义的验证规则,表示只支持国内手机号
    24. 'email' => 'required|email',
    25. 'name' => 'required|size:6,12'
    26. ];
    27. }
    28. }
  6. 但是由于 Lumen 已经精简掉了 Illuminate\Foundation\Http\FormRequest 这个类, 所以就没有办法沿用这种方式了
    那么换一种思路呢?实际上我们在 中间件 中去处理请求,也是能达到相同的效果:

    1. <?php
    2. namespace App\Http\Middleware;
    3. use App\Exceptions\ServerException;
    4. use App\Http\Form\Contract AS FormContract;
    5. use Closure;
    6. class Form
    7. {
    8. public function handle($request, Closure $next, $v)
    9. {
    10. $class = app('App\\Http\\Form\\' . ucfirst($v));
    11. if ($class instanceof FormContract) {
    12. $class->handle($request);
    13. } else {
    14. throw new ServerException(5000);
    15. }
    16. return $next($request);
    17. }
    18. }
  7. Lumen 中定义好 中间件 后,可以在需要启用表单验证的地方调用即可,例如在任意 控制器__constructor() 方法处使用:

    1. <?php
    2. namespace App\Http\Controllers;
    3. use Illuminate\Http\Request;
    4. class User extends Controller
    5. {
    6. public function __construct()
    7. {
    8. # 表示只对 edit + create 方法使用 form 中间件
    9. # form:user 同时也指定了表单验证类 App\Http\Form\User.php
    10. $this->middleware('form:user', ['only' => ['edit', 'create']]);
    11. }
    12. public function index()
    13. {
    14. $user = [
    15. 'name' => 'AdamTyn',
    16. 'email' => 'tynadam@foxmail.com',
    17. 'mobile' => '1888888888',
    18. ];
    19. return response()->json([
    20. 'data' => $user,
    21. 'code' => 0
    22. ]);
    23. }
    24. public function edit(Request $request)
    25. {
    26. // do somethings
    27. return response()->json($request->all());
    28. }
    29. public function create(Request $request)
    30. {
    31. // do somethings
    32. return response()->json($request->all());
    33. }
    34. }
  8. 对于更多的表单,则可以在 App\Http\Form 命名空间下继续创建对应的 表单验证类,具体实现可以通过示例 Code 去进一步了解
    经过上述一顿操作之后,可以在浏览器熟练地输入对应路由地址,即可看到:

    1. {
    2. "code": 4000,
    3. "message": "mobile => 手机号为必传参数. && email => email不能为空. && name => name不能为空.",
    4. "errors": {
    5. "mobile": [
    6. "手机号为必传参数."
    7. ],
    8. "email": [
    9. "email不能为空."
    10. ],
    11. "name": [
    12. "name不能为空."
    13. ]
    14. }
    15. }
  9. 眼尖的读者应该发现 (当然我也在前文的注释中悄悄地提及了),我们的错误信息不再只是英文,而是已经出现了更为具体的中文描述了
    还记得 前言 中提到的 本地化 吗?也即框架的 Illuminate\Validation\ValidationException 的异常信息都是会根据设置的语言进行格式化的,默认是使用英语。感兴趣的读者可以自行查看 resources/lang 目录:

Lumen业务篇:接口开发之自定义表单验证 - 图1

  1. 最后放出参考的示例 Code

    四、结语

  2. 本教程面向新手,更多教程会在日后给出。

  3. 随着系统升级,软件更新,以后的配置可能有所变化,在下会第一时间测试并且更新教程。
  4. 欢迎联系在下,讨论建议都可以,之后会发布其它的教程。