在 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 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 4

打卡工具人前来觐见~

4年前 评论

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

3年前 评论

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

3年前 评论

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