I have table with number field and I want input data with comma or dot (##,# or ##.#). After input this kind of value I want to change it to "dot only value".
$stuff = new Stuff();
$stuff->value='4,53';
print($stuff->value); // 4.53
Because I have many this kind of properties I wanted to use behaviour with event (onAfterSet) but this doesn’t work. Is any other method to do this kind of thing than overwrite setAttribute method? Can I change object attributes not using __set ora setAttribute methods?
Ok, I extends CActiveRecord class and overwrite setAttribute methods. Now I can change value without raise event, usefull when I change value on fly with behavior.
class ActiveRecord extends CActiveRecord
{
public function setAttribute($name, $value, $afterSet=true)
{
if($result=parent::setAttribute($name, $value) && $afterSet===true)
$this->afterSet($name);
return $result;
}
protected function afterSet($name)
{
if($this->hasEventHandler('onAfterSet'))
$this->onAfterSet(new CEvent($this, $name));
}
protected function onAfterSet($event)
{
$this->raiseEvent('onAfterSet',$event);
}
}
class DecimalBehavior extends CActiveRecordBehavior
{
public function events()
{
return array_merge(parent::events(), array(
'onAfterSet'=>'afterSet',
));
}
public function afterSet($event)
{
$model=$this->owner;
$name=$event->params;
$columns=$this->owner->getTableSchema()->columns;
if (preg_match(self::REGEX_DECIMALS,$columns[$name]->dbType,$m) && ($model->$name)!==null)
{
$value=strtr($model->$name,',','.')
$model->setAttribute($name, $value, false);
}
}
}
I don’t like it but it works, if someone has other way, I will be grateful.
Of course it works, but there is much shorter way:
class Stuff extends CActiveRecord/CModel/CFormModel
{
...
public function rules() // validation is performed each time when new data assigned
{
return array(
array('value', 'ensureFloat'), // this should be very first
// more rules here
);
}
public function ensureFloat($attribute)
{
$this->$attribute = (float) str_replace(',', '.', $this->$attribute);
}
}
If you don’t want validate attributes for some reasons, try to use virtual property:
/**
* @property float $value Table attribute
* @property float $valueFloat Virtual property to access attribute 'value'
*/
class Stuff extends CActiveRecord/CModel/CFormModel
{
...
public function setValueFloat($value)
{
$this->value = (float) str_replace(',', '.', $value);
}
public function getValueFloat()
{
return $this->value;
}
}
Thanks zless. Second aproach is not good for me, 'couse I need add many methods in many classes. I don’t know why I don’t use beforeValidate() or validate rule. Maybe it is the best solution, access to this kind of values only after correct validation.