从子模型yii2的字段中删除必需的



我有一个主模型,它有一个字段规则:

class User extends yiidbActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'users';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['username', 'email'], 'required'],
];
}
}

我必须马上说,我不能对这个模型进行更改,我只能在从这个继承的下一个模型中进行所有更改:

class UserForm extends User
{
public function rules(): array
{
return array_merge(
parent::rules(),
[ 
['username', 'safe', 'skipOnEmpty' => true],
]
);
}
}

最重要的是,在第一个模型中,用户名字段是必需的,但是现在我需要使它在填写表单时为空,并且在保存时将电子邮件字段的值复制到用户名字段。

对于复制,我使用以下函数:
public function beforeSave($insert)
{
if (empty($this->username)) {
$this->username = $this->email;
}
return parent::beforeSave($insert);
}

但是由于用户名字段是必需的,所以没有为我保存任何内容,我在子模型中所做的工作不起作用。如何在不编辑第一个模型的情况下使字段可选?

不能通过添加新规则来替换该规则。如果您这样定义规则,结果是requiredsafe规则都适用于username字段。

您必须在规则定义数组中找到required规则,并从该规则应用的属性中删除username。如果您知道规则定义总是在特定的位置上,这就很容易了。例如,如果它总是父模型的第一条规则:

public function rules()
{
$rules = parent::rules();
// the array diff is used to remove only 'username' field from list of attributes
$rules[0][0] = array_diff($rules[0][0], ['username']);        
return $rules;
}

如果你不知道required规则的位置,你需要使用一些循环来找到它。例如:

foreach ($rules as $rule) {
if (
$rule[1] == 'required'
&& (
(is_array($rule[0]) && in_array('username', $rule[0]))
|| (is_string($rule[0]) && $rule[0] == 'username')
)
) {
// rule found
}  
}

但是还有一个可能的解决方案解决你的问题。而不是复制beforeSave()回调email字段的值,你可以复制它在beforeValidate()回调。这样,当username字段被验证时,它将已经有email字段的值,并且它将通过验证。

您可以通过在规则中添加where子句来绕过所需的验证:

[['username', 'email'], 'required', 'when' => function() { return false; }],

由于函数总是返回false,因此永远不会应用验证器。

相关内容

  • 没有找到相关文章

最新更新