在 Yii2 中使用 Laravel 验证类

下载 Laravel 验证类

composer require illuminate/validation:~5.6

创建 Validate 类

use Illuminate\Translation\FileLoader;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Factory;
use yii\web\Controller;
use yii\base\Action;

class Validate {
   protected $validator = null;

   //网上抄的代码,获取 Laravel  Validate 实例
   private function getValidator(){
        if(is_null($this->validator)){
            $test_translation_path = __DIR__ . '/lang';
            $test_translation_locale = 'en';
            $translation_file_loader = new FileLoader(new Filesystem, $test_translation_path);
            $translator = new Translator($translation_file_loader, $test_translation_locale);
            $this->validator = new Factory($translator);
        }

        return $this->validator;
   }

   // 使用反射获取控制器的验证规则
   private function getRuleClass(Controller $controller,Action $action){
        $reflection = new ReflectionClass($controller);
        $comment = $reflection->getMethod($action->actionMethod)->getDocComment();

        return Tools::getDocComment($comment, 'validator');
   }

   // 验证控制器规则
   public function check(Controller $controller, Action $action){
       $ruleClass = $this->getRuleClass($controller,$action);

       // 如果控制器没有验证规则,直接返回 true
       if(empty($rules) || !class_exists($validator)){
          return true;
       }
       $ruleClass = new $ruleClass;
       // 获取表单数据,GET + POST
       $request = \Yii::$app->request;
       $input = array_merge($request->get(), $request->post());

       $rules = $ruleClass->rules();
       $messages = $ruleClass->messages();
       $attributes = $ruleClass->attributes();

       $result = $this->getValidator()->make($input, $rules, $messages, $attributes);

       // 验证失败抛出 ValidateException
       if ($result->fails()) {
          throw new ValidateException($result->messages()->first());
       }

       return ture;
   }
}

Tools::getDocComment :

public static function getDocComment($comment, $tag)
{
    if (empty($tag)) {
        return $comment;
    }

    $matches = [];
    preg_match("/" . $tag . "(.*)(\\r\\n|\\r|\\n)/U", $comment, $matches);

    if (isset($matches[1])) {
        return trim($matches[1]);
    }

    return '';
}

创建抽象 RuleClass 类

abstract class ValidateRules{
    /**
     * 验证规则
      *
     * @return array
     * @see https://laravel-china.org/docs/laravel/5.6/validation/1372
     */
     abstract public function rules(): array;

     abstract public function messages(): array;

     abstract public function attributes(): array;
}

创建具体的验证规则

class UserAddRules extends ValidateRules{
    public function rules(){
        return [
             'username' => 'required|email',
             'password' => 'required'
        ];
    }

    public function messages(){
        return [
             'required' => ':attribute 不能为空',
             'email' => ':attribute 必须为邮箱格式'
        ];
    }

    public function attributes(){
        return [
            'username' => '用户名',
            'password' => '密码'
        ];
    }
}

在控制器中加入验证

class UserController extends BaseController {
    /**
     * @validator app\Validate\UserAddRules
     */
     public function actionAdd(){
     }
}

使用注解将验证规则加入到控制器上,@validator 填写包含命名空间的完整类名

在 BaseController 中全局验证

public function beforeAction($action)
{
    try {
      $validate = new Validate();
      $validate->check($this, $action);
    } catch (\ReflectionException $e) {
      $this->responseJson(Status::SERVER_ERROR, $e->getMessage());
      return false;
    } catch (ValidateException $e) {
      $this->responseJson(Status::BAD_REQUEST, $e->getMessage());
      return false;
    }

    return parent::beforeAction($action); 
}

结束语

之前在开发 Yii 应用时,发现框架自带验证是在数据入库时进行的验证,不太符合项目需求,然后通过搜索发现 Laravel 验证包可以单独使用,尝试一番,还是挺不错的,在 RuleClass 中的编写方式与 Laravel 中的 Request 类一致,只有个别需要数据库验证的( unique 等)不能使用,可以实现 Illuminate\Contracts\Validation\Rule 进行自定义规则。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 4

打卡工具人前来觐见~

4年前 评论

“之前在开发 Yii 应用时,发现框架自带验证是在数据入库时进行的验证” 那是你不会用,yii2只要继承Model就能做数据校检,哪有说要在入库前校检,我们项目就是用models目录放参数校检类,用entities放数据库类。

3年前 评论

@seeMeFly 我这里指的入库可理解为【即将写入数据】,这有点浪费资源,如果数据不通过为什么会接触到数据库这层呢,在 Laravel 中直接在程序的最开始就拦截下来了,后续的程序逻辑都不需要考虑

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!