刘师傅 2018-09-20 18:22:09 3148次浏览 1条回复 0 0 0

近几天看了看yii2的模型场景机制和验证的部分,收获颇多,想来发一个话题跟大家好讨论下。 我觉得这个“非安全属性”没啥用,理由如下:
“安全属性”是对应场景下的属性,可以在load方法里完成赋值。如果不想被当前场景赋值,可以对某个字段加"!"前缀。使之成为“非安全属性”

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios[self::SCENARIO_CREATE] = ['contact_name','contact_tel','contact_addr'];
    $scenarios[self::SCENARIO_UPDATE] = ['!contact_name','contact_tel','contact_addr'];
    return $scenarios;
}

在SCENARIO_CREATE场景的时候,可以在load里完成['contact_name','contact_tel','contact_addr']的赋值;
在SCENARIO_UPDATE场景里,load()时只会对['contact_tel','contact_addr']完成赋值,不会对contact_name完成赋值。
可是我觉得,直接不写'!contact_name'也一样可以实现不对contact_name赋值。这样岂不是更好!
而至于contact_tel会不会被验证,和这里是不是安全属性没有关系! 第二个,就是safe验证器,按照文档所说https://www.yiichina.com/doc/guide/2.0/structure-models#safe-attributes safe验证器指明里不需要被验证的属性,比如:

public function rules()
{
    return [
        [['title', 'description'], 'safe'],
    ];
}

我觉得safe验证器也没啥用,safe仅仅是一个傀儡验证器,因为safeValidator只有两个空方法。
如果是这样的话,还不如不把safe写在rules方法里呢,这样['title', 'description']这些属性们当然不会被验证,更不会走safe验证器,还提高效率呢!
话说回来,如果要是有点用的话,那就是【提示,提醒】作用而已,而已
它会告诉你"!contact_name"不会被load赋值;告诉你['title', 'description']不会被验证。

  • 回复于 2019-01-13 10:51 举报

    看了楼主的文章也是深感共鸣,感觉有所收获。
    但是仔细看了下文档结合自己的代码输出,觉得这个里面的内容还是有出入的。

    首先,引用非安全属性的部分原话

    你可能想验证一个属性但不想让他是安全的, 可在scenarios()方法中属性名加一个惊叹号 !

    是想【验证】属性,但是不想让他安全。他想说的是验证,也就是说这个属性可能被自己直接赋值了

    $model->contact_name = 'xxx'; // 为前提,才能让你此次的load通过,没有想到具体场景,假设场景就是你必须验证你的姓名是否为真(假设验证之后你的contact_name 才能赋值),然后load才能通过

    其次,safe验证

    safe验证器和不写还是大有区别的,不写在前台load的时候就不会被load上,而safe验证器是指的前台可以load随意任何值都可以,但是感觉很不安全是的。

    不知道理解是否正确,帖子也有段时间了,挖出来也是想着更多的讨论。
    敬礼。

    1 条回复
    回复于 2019-01-15 19:44 回复

    首先这个话题我以为石沉大海了,其实应该有好多人看了但是并没有提出问题。互相学习下还是好的,尤其遇到了理解不一致的东西。
    我还是拆成两个部分来理解:
    第一,首先理解“安全属性”和load的关系。
    “安全属性”这个概念的意思,就是说可以在对应场景下被load赋值的属性。这个在文档第一句话就说了:

    块赋值只应用在模型当前scenario 场景yii\base\Model::scenarios()方法 列出的称之为 安全属性 的属性上
    

    块赋值就是指load()方法赋值。被赋值的属性就是安全属性。
    你说的那个“想验证一个属性而又不想它是安全的”。我觉得你说得是对的。没有问题。对某些安全属性前缀加上"!"号后它就不会在load时被赋值了,它就是“非安全属性”了。当然你应该在这之前或之后用其它方法赋值。

    第二个:对于safe验证器的理解来说,我还是坚持我的看法,

    safe验证器写与不写都不影响load()过程safe紧紧是声明了不验证的属性而已这些属性可以是load赋值的或者直接赋值的都无所谓

    文档上有一段话是这么翻译的,但是我觉得有理解歧义:

    为此,提供一个特别的别名为 safe 的验证器来申明 哪些属性是安全的不需要被验证, 如下示例的规则申明 title 和 description 都为安全属性。
    

    上面说

    “哪些属性是安全的不需要被验证”
    

    我觉得“不需要被验证”说对了,因为safe验证器就是一个傀儡验证器,没有验证过程。
    但是

    “哪些属性是安全的”
    

    这部分。这里的“安全”,我觉得应该不是前面所说的“安全属性”里的“安全”。这里的“安全”就是我们所说的,主观上认为这些属性没有问题,没有漏洞,可以不走,也不需要走验证过程,“很安全”。所以这里和load()没有关系。

    再回到第一句文章的原话:

    你可能想验证一个属性但不想让他是安全的可在scenarios()方法中属性名加一个惊叹号 !
    

    我觉得把这句话包含了load()和验证两个过程,把它俩加一块理解就可以了:
    “想验证一个属性”,说的是后面的rules里的规则验证过程;
    “不想让他是安全的”是说不希望被load()赋值。
    就这样理解。你觉得咋样?我觉得很有意思。

您需要登录后才可以回复。登录 | 立即注册