Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2: custom setter method/data transformation doesn't work on ActiveRecord?

I'm trying to do data transformation on an attribute by using the setter method setUsr_firstname for an attribute that is named usr_firstname.

class User extends ActiveRecord implements IdentityInterface {

    public function rules() {
        return [
            [['usr_firstname', 'usr_lastname', ... ], 'required'],
            ...
        ];
    }

    ...

    public function setUsr_firstname($value) {
        $this->usr_firstname = fix_wrong_title_case($value);
    }
}

Then I do the following:

$model = new User(['scenario' => User::SCENARIO_REGISTER]);
$model->usr_firstname = 'John';

But the setter method is never called! I have tried naming the method all kinds of things - eg. setUsrFirstname - but nothing works. How do I get this to work?

UPDATE

Figured out it doesn't work for any ActiveRecord attribute, with or without an underscore in the attribute name.

like image 478
TheStoryCoder Avatar asked Feb 05 '23 21:02

TheStoryCoder


1 Answers

Setter method is not called in case of properties declared directly or Active Record attributes (no matter if it's with the underscore or not).

Active Record's magic __set method assigns value directly to the mapped attribute.

You can achieve something similar with new virtual attribute:

public function setUsrFirstname($value)
{
    $this->usr_firstname = doSomethingWith($value);
}

public function getUsrFirstname()
{
    return $this->usr_firstname;
}

So now you can use it like:

$this->usrFirstname = 'John';
echo $this->usrFirstname;

If you want to modify the attribute in the life cycle of AR you can:

  • use FilterValidator to change it during validation,
  • override model's afterFind() method to change it after DB fetch,
  • override model's beforeSave() method to change it before saving to DB,
  • prepare behavior that can do all the things above,
  • prepare method to be called directly that will change it (you can use the first setter method for this; no need to call validate() and clearErrors()).
like image 182
Bizley Avatar answered Feb 08 '23 09:02

Bizley