如何在没有验证规则的Yii2中创建场景?

时间:2016-09-25 17:50:08

标签: validation yii2 scenarios validationrules yii-validation

我有 MyEntity.php 模型。作为模型脚本的一部分,有一些规则和一些场景定义:

then

我需要能够拥有不同的场景,并且对于不同的操作,只有某些验证(通过参数)才能生效。例如,scenario_one for actionOne,scenario_two for actionTwo等。

以下是控制器的一小部分代码:

public function rules()
{
    return [
        [['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required'],
        [['myentity_id'], 'integer'],
        [['myentity_title', 'myentity_content'], 'string', 'max' => 120],
        [['myentity_date'], 'safe'],            
    ];
}

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios['scenario_one'] = ['myentity_id', 'myentity_title'];
    $scenarios['scenario_two'] = ['myentity_id', 'myentity_content'];
    return $scenarios;
}

现在我想要一个不应该进行任何验证的scenario_three。我会在代码中进行额外的检查,以防止在数据库中存储时出现故障。我只需要确保不会应用任何验证,因为它会阻止我的表单提交。如果我不应用任何方案,则应用默认方案(所有列出的验证都将处于活动状态,这与我需要的方案完全相反)。

2 个答案:

答案 0 :(得分:5)

为了能够做到这一点,你需要做一些事情(包括你自己几乎做过的事情):

  • 在您的控制器中,写下scenarios()

  • 在模型中,添加一个额外的场景阵列' scenario_three'在$scenarios['scenario_three'] = ['myentity_id', 'myentity_content']; 方法:

像这样:

rules()
  • 最后,except中需要进行大多数更改,因为您需要添加包含或排除特定方案的位置。

基本上,在每条规则中,您现在可以编写scenario_three条件,并指出哪些属性不符合哪种情况。所以在你的例子中,让我们说,让我们排除[['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required', 'except' => 'scenario_three'], [['myentity_id'], 'integer', 'except' => 'scenario_three'], [['myentity_title', 'myentity_content'], 'string', 'max' => 120, 'except' => 'scenario_three'], [['myentity_date'], 'safe'], 的所有属性:

{{1}}

这是如何忽略规则的一个不同的解决方案,但我觉得这更有吸引力,因为将来更容易为这个场景添加/删除特定属性,并且对于其他开发人员也会更容易(如果有更多只是你)了解你正在尝试做什么。

但我认为@ iStranger的解决方案也有效(更简单)。

答案 1 :(得分:4)

如果我正确理解了您的问题,您可以将scenario_three指定为当前方案:模型将找不到匹配的规则,并且将跳过验证检查。

public function actionThree($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_three';
    .
    .
    .
}

<强> UPD: 但是,我严格建议明确定义所有方案和相应的活动属性(在scenario方法中)并删除$scenarios = parent::scenarios();,因为它可能会导致不必要的影响。父实现主要是为了与Yii1向后兼容而开发,Yii1没有scenarios()方法。通常,如果您覆盖scenarios()方法,则不应将明确定义的方案与父实现合并。