专栏首页热爱ITyii2 scenarios()如何理解?? [ 2.0 版本 ] 转

yii2 scenarios()如何理解?? [ 2.0 版本 ] 转

为什么80%的码农都做不了架构师?>>>

最近在使用场景的时候碰到一些不解的问题,我简单模拟下: 我新建一张表info,有name和age2个字段 模型代码:

public function rules()
    {
        return [
            [['age'], 'integer'],
            [['name'], 'string', 'max' => 22],
            ['name','required','message'=>'姓名不能为空','on'=>['add','update']],
            ['age','required','message'=>'年龄不能为空','on'=>'add'],
            ['age','isMath','on'=>'add']
        ];
    }
    
    public function scenarios()
    {
        return [
            'add' => ['age','name'],
            'update'=>['name']
        ];
    }

当我进行编辑操作的时候,使用$model->scenario = 'update';也就是使用update场景,出现的结果是:name改变了age竟然没有更改,我把代码修改下

public function scenarios()
    {
        return [
            'add' => ['age','name'],
            'update'=>['name','age'] //这里加个age
        ];
    }

这个时候正常修改了name和age字段

还有就是我不重写scenarios()方法,也是正常执行验证的

所以有2个问题: 1.重写scenarios()方法,具体应该在什么时候? 2.上面代码加个age和不加age区别是什么?在update场景下我只验证name字段,age只在add场景下,但是在update场景下'update'=>['name']没有写age就不能修改age字段?????

答:

默认情况下,scenarios() 返回的是一个关系数组,键是模型中所有可用的场景,值是场景对应的 active attributes 列表。active attributes 有两个特点:

  • 如 @koko 所说,调用 validate() 时仅会验证 active attributes
  • 使用 $model->load() && $model->save() 保存数据时只保存 active attributes;

在你的例子中,把 'age' 从 update 场景中移除意味着 age 不再是 active attribute, 这就是为什么对 age 的修改没有写入数据库的原因。

默认的 scenarios() 过程(以你的例子中声明的规则为例)

scenarios() 会进行两次遍历操作。首先遍历 rules 中声明的规则,把所有可用的场景找出来,并初始化数组,以你的例子中的 rules 为例,值为:

[
    'default' => [], // 框架自带的默认场景
    'add' => [],
    'update' => [],
]

第二次遍历时,对每个 rule 中声明的 attributes “对号入座”,如果 rule 中不带 'on' 属性,表示该属性所属的规则适用于所有场景(例如 [['age'], 'integer']), 会将 'age' 追加到所有场景的 active attibutes 列表中;如果指定了场景值,仅在对应的场景下的active attributes 内追加。

经过这两次遍历,scenarios() 最终返回的值将是:

[
    'default' => ['age', 'name'], 
    'add' => ['age', 'name'],
    'update' => ['age', 'name'],
]

可以看到, 'age' 在每个场景中都是 active attribute, 这就是为什么在你不重写 scenarios() 的情况下,对 age 的修改也能保存的原因。

了解了这个过程,我的理解是:在大多数情况下,是不需要重写 scenarios() 的,通过配置 rules() 来改变 scenarios() 的返回值,而不是直接手动覆盖 sceanrios(). 覆盖带来的一个明显的弊端是:你的精力被分散到了两个方法内(rules() 和 scenarios()),假设将来你的 info 表又新增了一列,在 rules() 追加新的规则的同时,你还要修改重写后的 scenarios(), 把新增加的列追加进去使其成为 active attribute,否则就会出现新增列的数据无法存入数据库。使用默认的 scenarios() 的话,只需要将精力放在 rules() 上即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 模糊查询 原

    SELECT p, product_name, factory_sn   FROM product_info where product_name ilike...

    双面人
  • PHP中使用Elasticsearch 转

    会自动加载合适的版本!我的php是5.6的,它会自动加载5.3的elasticsearch版本!

    双面人
  • 史上最全Python面向对象编程 转

    在多函数程序中,许多重要的数据被放置在全局数据区,这样它们可以被所有的函数访问。每个函数都可以具有它们自己的局部数据,将某些功能代码封装到函数中,日后便无需重复...

    双面人
  • 在Google Cloud platform上的Kubernetes集群部署HANA Express

    在Google Cloud platform的Kubernetes cluster上,新建一个hxe.yaml文件:

    Jerry Wang
  • 再论:关于 equals 和 hashCode

    上篇 关于 equals 和 hashCode 关于 equals 和 hashCode 的基本性质已经论述过了。

    shengjk1
  • Python operator.itemgetter

    我们用sorted对年龄进行排序,参数key传入lambda,指定要根据哪个元素进行排序

    致Great
  • BERT源码分析PART I

    BERT模型也出来很久了, 之前有看过论文和一些博客对其做了解读:NLP大杀器BERT模型解读,但是一直没有细致地去看源码具体实现。最近有用到就抽时间来仔细看看...

    AINLP
  • 【BERT】源码分析(PART I)

    最近在看paddle相关,于是就打算仔细过一遍百度ERNIE的源码。之前粗看的时候还没有ERNIE2.0、ERNIE-tiny,整体感觉跟BERT也挺类似的,不...

    zenRRan
  • BERT源码分析(PART I)

    最近在看paddle相关,于是就打算仔细过一遍百度ERNIE的源码。之前粗看的时候还没有ERNIE2.0、ERNIE-tiny,整体感觉跟BERT也挺类似的,不...

    kaiyuan
  • JDK1.9-Set接口

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    cwl_java

扫码关注云+社区

领取腾讯云代金券