TheStoryCoder
TheStoryCoder

Reputation: 3640

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.

Upvotes: 6

Views: 3286

Answers (1)

Bizley
Bizley

Reputation: 18021

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()).

Upvotes: 12

Related Questions