在 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 协议》,转载必须注明作者和本文链接
工具人 打卡
打卡工具人前来觐见~
“之前在开发 Yii 应用时,发现框架自带验证是在数据入库时进行的验证” 那是你不会用,yii2只要继承Model就能做数据校检,哪有说要在入库前校检,我们项目就是用models目录放参数校检类,用entities放数据库类。
@seeMeFly 我这里指的入库可理解为【即将写入数据】,这有点浪费资源,如果数据不通过为什么会接触到数据库这层呢,在 Laravel 中直接在程序的最开始就拦截下来了,后续的程序逻辑都不需要考虑