behaviors could use improvments

I was attempting a create a TimeBehavior the other day that could handle date/times within forms. It would create and control up to four different fields per date: a day field, and hour field, a minute field, and an am/pm field. In afterSave() it would splite the date into the different sub-fields (hours, minutes, etc), and in afterValidate(), it would merge them back together. There was a helper function that went along with this for help creating the time fields…

The big let-back was that I could not define attributes for the model within the behavior. I needed to do this dynamically, so they could be created on-the-fly. This is not possible. I need it to define eg $<time>Hour, $<time>Minute, etc, where <time> is replaced with the name of the main field (probably the column name in the database)

I propose the following. These would mostly be used in behaviors I believe, but is not limited to that.




//Adds the attribute to the model (on-the-fly), so that it can be accessed with $model->{$name} (eg __get())

CModel::addAttribute($name)


//makes an attribute safe on-the-fly

CModel::addSafeAttibute($name, $scenario=null)


//adds validation rule on-the-fly

CModel::addValidationRule($attribute, $rule, $options=array())


//adds relation on-the-fly

CModel::addRelation($name, $type, $foreignModel, $attribute, $options=array())


//not as useful

CModel::addAttributeLabel($attribute, $label)



Whatcha think? I think it would allow people to create more dynamic behaviors, and add more dynamic abilities in general.

As these properties have nothing to do in the model, not even dynamically, and only related to the given behavior, I’d say no.

I’d rather make my forms inherit some container abilities to make unknown attributes usable via __get() and __set().

Allowing runtime modifications outside from the model seems like a bad practice to me.

Perhaps it would be better if the extra attributes are contained in the behavior, so not to pollute the models. Then __get() would look in the behaviors. Maybe Behaviors should have a new method like the following:?




class NNBehavior extends CActiveRecordBehavior {

	public method attributes() {

		return array('foo', 'bar'=>'defaultValue');

	}	

}



Or perhaps have public attributes visible to the model while protected ones are not.

What I really need is a way for abstracted (dynamically named) attributes to be inserted into the behavior via CModel::setAttributes(). Any ideas?

If you reach behaviors’ attributes, you also violate their original purpose - modifying owner’s behavior without touching its internals.

I think we already have a ticket for this: http://code.google.com/p/yii/issues/detail?id=264

That seems to be about preinit()…?

It’s about allowing adding new properties via behaviors.