I have a main model and it has a field rules:
class User extends yiidbActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'users';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['username', 'email'], 'required'],
];
}
}
I must say right away that I cannot make changes to this model, I can make all changes only in the next model that will be inherited from this:
class UserForm extends User
{
public function rules(): array
{
return array_merge(
parent::rules(),
[
['username', 'safe', 'skipOnEmpty' => true],
]
);
}
}
The bottom line is that in the first model the username field is required, but now I need to make it so that when filling out the form it is empty, and when saving the value of the email field is copied to the username field.
For copying I use the function:
public function beforeSave($insert)
{
if (empty($this->username)) {
$this->username = $this->email;
}
return parent::beforeSave($insert);
}
But due to the fact that the username field is required, nothing is saved for me, what I did in the child model does not work. How can I make a field optional without editing the first model?
2
Answers
You could bypass the required validation by adding a where clause in your rule:
Since the function always returns false, the validator is never aplied.
You can’t replace the rule by adding another. If you define rules like that, the result is that both,
required
andsafe
rule are applied forusername
field.You have to find the
required
rule in rules definition array and removeusername
from attributes the rule applies to.It can be easy if you know that the rule definition will always be in specific position. For example if it’s always the first rule in parent model:
If you don’t know the position of
required
rule, you will need to use some cycle to find it. For example like this:But there is another possible solution to your problem. Instead of copying the value of
email
field inbeforeSave()
callback you can copy it inbeforeValidate()
callback. That way when theusername
field is validated it will already have the value of email field and it will pass validation.