Changing on the fly input data in AR

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.