LumenLaravel开发实践PHP经验分享

Laravel业务篇:接口开发之自定义表单验证

2019-02-15  本文已影响0人  我爱余倩

一、前言

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

二、开始

  1. 因为 Lumen 已经是精简版的缘故,所以框架本身并没有对 表单验证 做过多的处理。
    默认的,如果沿用 Laravel 中的 validator() 方法验证错误的表单,将会抛出一个 Illuminate\Validation\ValidationException 的异常:
     # Illuminate\Validation\Validator.php
     public function validate()
     {
         if ($this->fails()) {
             throw new ValidationException($this);
         }
    
         return $this->validated();
     }
    
  2. 既然框架已经抛出异常了,那么我们只要去捕获此类异常,然后根据自定义的格式输出接口,改变原有的渲染方式即可。
     # 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);
     }
    

三、详解

  1. 对于复杂的表单提交,如果是在 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'
             ];
         }
     }
    
  2. 但是由于 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(4000);
             }
    
             return $next($request);
         }
     }
    
  3. 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());
         }
     }
    
  4. 对于更多的表单,则可以在 App\Http\Form 命名空间下继续创建对应的 表单验证类,具体实现可以通过示例 Code 进行了解。
    经过上述一顿操作之后,可以在浏览器熟练地输入对应路由地址:
     {
         "code": 4000,
         "message": "mobile => 手机号为必传参数. && email => email不能为空. && name => name不能为空.",
         "errors": {
             "mobile": [
                 "手机号为必传参数."
             ],
             "email": [
                 "email不能为空."
             ],
             "name": [
                 "name不能为空."
             ]
         }
     }
    
  5. 眼尖的读者应该发现 (当然我也在前文的注释中悄悄地提及了),我们的错误信息不再只是英文,而是已经出现了更为具体的中文描述了。
    还记得 前言 中提到的 本地化 吗?也即框架的 Illuminate\Validation\ValidationException 的异常信息都是会根据设置的语言进行格式化的,默认是使用英语。感兴趣的读者可以自行查看 resources/lang 目录:
resources/lang
  1. 最后放出参考的示例 Code

五、结语

  1. 本教程面向新手,更多教程会在日后给出。
  2. 随着系统升级,软件更新,以后的配置可能有所变化,在下会第一时间测试并且更新教程;
  3. 欢迎联系在下,讨论建议都可以,之后会发布其它的教程。
上一篇下一篇

猜你喜欢

热点阅读