让webman和laravel一样实现自动表单验证

lpz

从laravel转到webman发现表单验证不能使用依赖注入自动验证所以改造了一下。

实现思路

1、创建一个BaseValidate基类,基类继承app\validate,校验类继承基类
2、在基类的构造方法里调用check方法,这样在依赖注入的时候就会自动进行校验,校验失败抛出异常
3、在异常处理类中接住,并自定义响应

BaseValidate基类代码

<?php
declare (strict_types=1);

namespace app\validate;

use think\Validate;

class BaseValidate extends Validate
{

    public function __construct() {
        if ($this->scene){
            $scene = request()->action;
            if (!$this->hasScene($scene)){
                return;
            }
            $this->scene($scene);
        }
        $this->failException()->check(request()->all());
    }

}

校验类代码

<?php
declare (strict_types=1);

namespace app\validate;

use app\validate\BaseValidate;

class TestValidate extends BaseValidate
{

    protected $rule = [
        'name' => 'require',
        'age'  => 'require',
    ];

    protected $message = [
        'name.require' => '名称必须',
        'age.require'  => '年龄必须',
    ];

    protected $scene = [
        'edit' => ['name'],
        'del' => ['age'],
    ];

}

异常处理类代码

<?php
/**
 * This file is part of webman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author    walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link      http://www.workerman.net/
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 */

namespace support\exception;

use think\exception\ValidateException;
use Throwable;
use Webman\Exception\ExceptionHandler;
use Webman\Http\Request;
use Webman\Http\Response;

/**
 * Class Handler
 * @package support\exception
 */
class Handler extends ExceptionHandler
{
    public $dontReport = [
        BusinessException::class,
    ];

    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    public function render(Request $request, Throwable $exception): Response
    {
        if ($exception instanceof ValidateException) {
            return json([
                'code' => 500,
                'msg' => $exception->getMessage(),
                'data' => null
            ]);
        }
        if(($exception instanceof BusinessException) && ($response = $exception->render($request)))
        {
            return $response;
        }

        return parent::render($request, $exception);
    }

}

控制器调用(1)

<?php

namespace app\controller;

use app\validate\TestValidate;

class IndexController
{

    public function edit(TestValidate $validate)
    {
        return 'edit';
    }

    public function del(TestValidate $validate)
    {
        return 'del';
    }

}

控制器调用(2)

<?php

namespace app\controller;

use app\validate\TestValidate;

class IndexController
{

    public function __construct()
    {
        new TestValidate();
    }

    public function index()
    {
        return 'index';
    }

    public function edit()
    {
        return 'edit';
    }

    public function del()
    {
        return 'del';
    }

}

测试

截图
截图
截图
截图
截图

505 2 1
2个评论

tuhrx

看了你的代码,立马看了Controller初始化的代码,其实我的想法跟你的一样,我是在request对象初始化那一块钻了牛角尖。非常感谢分享!!!🙏

贴上我的实现:
我用的是 respect/validation 库

<?php
declare(strict_types=1);

namespace app\requests;

use Respect\Validation\Exceptions\ValidationException;

class FormRequest
{
    protected array $rules = [];
    protected array $messages = [];
    protected array $data = [];
    private \Webman\Http\Request|\support\Request|null $request;

    public function rules(): array {
        return [];
    }

    public function messages(): array {
        return [];
    }

    /**
     * @throws \app\Exceptions\ValidationException
     */
    public function __construct() {
        $this->request = request();
        $this->data = $this->all();
        $this->validateResolved();
    }

    /**
     * @return void
     * @throws \app\Exceptions\ValidationException
     */
    public function validate(): void
    {
        $this->rules = $this->rules();
        $this->messages = $this->messages();

        $errors = [];

        foreach ($this->rules as $field => $rule) {
            try {
                $rule->assert($this->data[$field] ?? null);
            } catch (ValidationException $exception) {
                $errors[$field] = $exception->getMessages($this->messages[$field] ?? []);
            }
        }

        if (!empty($errors)) {
            throw new \app\Exceptions\ValidationException($errors);
        }
    }

    /**
     * 解析时自动验证
     * @throws \app\Exceptions\ValidationException
     */
    public function validateResolved(): void
    {
        $this->validate();
    }

    public function __call($method, $arguments) {
        if (method_exists($this->request, $method)) {
            return call_user_func_array([$this->request, $method], $arguments);
        }
        throw new \Exception("Method $method does not exist");
    }

    public function __get($name) {
        if (property_exists($this->request, $name)) {
            return $this->request->$name;
        }
        throw new \Exception("Property $name does not exist");
    }

    public function __set($name, $value) {
        if (property_exists($this->request, $name)) {
            $this->request->$name = $value;
        } else {
            throw new \Exception("Property $name does not exist");
        }
    }

    public function __isset($name) {
        return isset($this->request->$name);
    }

    public function __unset($name) {
        unset($this->request->$name);
    }
}
  • 暂无评论
tanhongbin

和写在中间件 有一曲同工之妙

  • 暂无评论

lpz

220
积分
0
获赞数
0
粉丝数
2022-09-22 加入
×
🔝