11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

yii2 数据模型 - 基于场景的验证

  • 2019-09-23
  • 本文字数:2500 字

    阅读完需:约 8 分钟

yii2数据模型-基于场景的验证

系统交互的过程中,对数据的接收方来说,对数据的格式、内容的校检、验证至关重要。比如后端在接受注册用户的数据时候,会对传送过来的邮箱、手机号、用户密码、填写的外链 url、注册地点 ip 等每种格式都需要验证是否符合对应的规范,有时还需要根据数据库中的现有数据,判断新注册的登陆用户名是否重复,有时不只是单纯的验证某一项,需要依赖对其他的项的验证结果来决定是否验证,比如邮箱跟手机号两个二选一即可。有时换到另外一种场景,如在更新用户信息的时候,仔细观察后就会发现上述验证规则有很大的重复。

针对这些问题,在 yii2 中是使用元编程的思路,给出了一种很优雅的解决方式-Validator。

yii2 的 Validator 实现跟数据模型 Model 有很多的互相交互、依赖。下面给出以下从 Model 层面的使用样例。


样例

针对上述提到的几个问题,在 yii2 中的解法如下,仅仅使用了一个数组就描述清楚的每个字段在不同场景下的验证规则,关于核心验证器的用法参考 yii2 权威指南-核心验证器相关章节:


 1class User extends yii\base\Model  { 2    public $mobile; 3    public $email; 4    public $username; 5    public $password; 6    public $reg_ip; 7    public $weibo_url; 8 9    const  SCENARIO_REG = 'reg';1011    public function rules() {12        return [13            //邮箱、手机号必有一个不为空14            [['email'], 'required', 'when' => function(self $model) {15               return !(new \yii\validators\RequiredValidator())16                            ->validate($model->mobile);17            }],18            //检查邮箱、ip的数据格式19            ['email', 'email'],20            ['reg_ip', 'ip'],21            //数据库中值唯一22            ['username','unique', 'on' => [23                self::SCENARIO_REG24            ], 'message' => '你的用户名TMD热门了,已被占用,再换一个吧!!!'],25            //用户名,密码长度至少为8,最多为1626            ['username', 'string','length' => [8,16]],27            ['password', 'string', 'min' => 8, 'max' => 20],2829             //用户名只含有52英文字母表字幕及数字,且只能以字母开始30            ['username', 'match', 'pattern' => '/[a-zA-Z]+[a-zA-Z0-9]*/'],31        ];32    }3334}3536$model = new User();37$model->setScenario('default');38$model->load($_POST, '');39if(!$model->validate()) {40    Yii::error($model->getErrors(),'DATA_VALIDATION');41    ...42}4344...
复制代码


rules()返回数组结果中的每一个数组元素,分别是针对不同的属性在不同的场景下的验证规则,其格式含义如下:


[attributes [] | String, Validator | Closure | String, Validator 子类实例初始化列表]


  • attributes [] | String , 如果只有一个属性,其可以是一个字符串,否则为数组形式

  • Validator | Closure | String, 此处可以为 yii2 的子类实例, 或是是 Yii2 内部实现的一组核心验证器(都是 Validator 的子类)的别名, 如果没有这个别名的验证器,就会使用数据模型 Model 子类实例中同名的方法,最后,其可以直接是一个闭包。后两种方式都是封装在一个 InlineValidator 中实现的。

  • 再往后就是一些关联数组,每一对都是针对每个 Validator 属性的初始化。


如此清晰易读的语法形式和初始化列表功能的存在,完全得益于 yii2 的基于配置这个特性。


场景 scenario,属性 attribute

场景本身也没什么,就是用来告诉验证器当前是在哪个场景之下,例如注册用户、更新用户信息可以设置两个场景。实际使用时,通过 setScenario 设置完场景,在后面调用 validate 时 yii2 就可以自动选定对应场景下的规则进行验证,上列中用 on 指定规则在那些场景下启用,上例中没有使用 on 的规则,在所有场景下都会进行验证其内的属性。


rule()方法返回结果数组中每条验证规则内的活动属性(attribute),既用来说明那些属性是安全的,可以对类中同名成员变量进行块赋值, 也表示,调用 validate 时,将会使用本条规则对活动属性进行验证。


load()


本例是对 rule 返回安全的活动属性进行块赋值到类实例的成员变量,


on except 属性:


on 是用来指定当前的验证规则是在那些场景下启用。


  • 没有指定 on 属性的字段,规则会在所有场景中都被启用

  • on 的值可以为字符串,‘scenarino’ 单个场景中起作用

  • on 的值可以为数组[‘scenrino1’,scenarino2]多个场景中起作用


except 和 on 类似,只是用来说明那些场景不启用当前规则。有个值得注意的问题就是 on 和 except 同时指定的时候只有 on 才会起效。


message 属性


当针对属性的验证规则失败的时候,用于指定自定义的错误返回信息


scenarios()


这个数据模型 Model 的方法返回每个场景及其对应的活动属性(active attribute)数组。


1  [2      'scenario1' => ['active attribute1','active attribute2' ]3      'scenario2' => ['active attribute1','active attribute2' ]4      'scenario3' => ['active attribute1','active attribute2' ]5  ]
复制代码


在使用 setScenario 设置完当前的场景后,scenarios()返回的场景对应的安全的活动属性可以进行块赋值(即同时可以对多个属性进行赋值),上例中使用 load() 进行的块赋值。如果不想在 scenario1 中对某些活动属性使用块赋值,只需要在属性名前加!标记为非安全的活动属性即可。


1      'scenario1' => ['!active attribute1','active attribute2' ]
复制代码


如果这个方法没有被覆盖重写,默认的 Model 中的返回值是根据 rule()的返回数组生成的。其中:


  • 有一个默认场景 default,所有没有使用 on except 的其中的属性的都属于此场景

  • 返回 rules 里面发现的所有场景和对应的属性,默认是属性是安全的可以进行块赋值

  • 可以在每个属性前加一个!标记属性是非安全的,不使用块赋值。


总结

以上就是数据模型基于场景的验证的简单分析。


作者介绍:


杨振振,贝壳找房 SRE PHP 研发工程师,目前负责 HOLONET 项目。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/N5za6Qod7GzjZe1nd6gnGQ


2019-09-23 09:48561

评论

发布
暂无评论
发现更多内容

从脚本到剪辑,影像大师亲授的后期制作秘籍

博文视点Broadview

是什么影响了MySQL性能?

TimeFriends

8月月更

8月份DB-Engines 数据库排行榜最新战况

雨果

数据库

Gartner再次重申了“数据编织”的重要价值

雨果

数据编织

OneFlow源码解析:算子指令在虚拟机中的执行

OneFlow

虚拟机 源码解析 算子

中小规模网站架构

舟停江吹雪

Linux

一起畅聊「云+操作系统」!龙蜥社区亮相阿里巴巴开源开放周,完整议程来了

OpenAnolis小助手

数据库 操作系统 龙蜥社区 阿里巴巴开源开放周 开源共享

2022年裁员潮,失业程序员何去何从?

千锋IT教育

STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建

DS小龙哥

8月月更

企业如何判断数据治理是否成功?

雨果

数据治理

SQL与NoSQL最终会走向融合吗?

雨果

nosql sql

快速上手,征服三种不同分布式架构调用方案

知识浅谈

分布式 8月月更

学Python爬虫,不看看m3u8文件如何加密?i春秋 m3u8 文件加密解析

梦想橡皮擦

Python 爬虫 8月月更

JWT 实现登录认证 + Token 自动续期方案

CRMEB

Open Office XML 格式里如何描述多段具有不同字体设置的段落

Jerry Wang

xml 微软 Office 8月月更 openOffice

50个Java面试必问的面试题,这里都给你整好了

千锋IT教育

GPU加速Pinterest推荐模型,参数量增加100倍,用户活跃度提高16%

OneFlow

机器学习 深度学习 gpu

开源一夏 | mysql5.7安装部署-yum安装

zhangpfly

MySQL 开源 linux运维 #开源 8月月更

Kyligence 通过 SOC 2 Type II 审计,以可信赖的企业级产品服务全球客户

Kyligence

国际权威鉴证标准 企业级数据分析

谷歌数据中心发生“电力事故”造成 3 人受伤

雨果

数据中心 谷歌

Gitlab刚发布一项禁止使用 Windows 的公司政策

雨果

gitlab Github'

C++运算符重载(二)之左移运算符重载

CtrlX

c c++ 进阶 重载 8月月更

使用CSS实现多种Noise噪点效果

dragonir

CSS html html5 css3

yii2数据模型-基于场景的验证_文化 & 方法_杨振振_InfoQ精选文章