I want to discuss the addition of a couple of additional events to models. Namely:
onGet
onSet
onIsset
onUnset
onCall
They all would be fired when accessing an undefined property / calling an undefined method (a.k.a. when calling a PHP magic method). I only see a problem with an apropriate naming schema, because there’s no before or after in this case. Existing events use e.g. afterConstruct(). This method fires the event and can be overridden in child classes. We would need something different and on is already taken, because it defines the event.
So for now let me use these names the events:
onMagicGet
onMagicSet
onMacicIsset
onMagicUnset
onMagicCall
Please bare with me - i don’t really like this either, but let’s have a look at a possible implementation using this schema in CModel:
// Define magic methods
// (called from all child implementations, e.g. from AR, as last ressort)
public function __get($name)
{
return $this->magicGet($name);
}
public function __set($name,$value)
{
$this->magicSet($name,$value);
}
public function __call($name,$args)
{
return $this->magicCall($name,$args);
}
// TBC ...
// Define events
public function onMagicGet($event)
{
$this->raiseEvent('onMagicGet',$event);
}
public function onMagicSet($event)
{
$this->raiseEvent('onMagicSet',$event);
}
public function onMagicCall($event)
{
$this->raiseEvent('onMagicCall',$event);
}
// TBC ...
// To ease overriding in child models:
public function magicGet($name)
{
if ($this->hasEventHandlers('onMagicGet')
{
$event=new CMagicModelEvent;
$event->name=$name;
$this->onMagicGet($event);
return $event->value;
}
}
public function magicCall($name,$args)
{
if ($this->hasEventHandlers('onMagicCall')
{
$event=new CMagicModelEvent;
$event->name=$name;
$event->args=$args;
$this->onMagicCall($event);
return $event->value;
}
}
// Required to propagate getter/setter/call information to event handlers
class CMagicModelEvent extends CEvent
{
// Name of get/set var or method
public $name;
// method arguemnts
public $args;
// Value to set / return from called method
public $value;
}
How can this be useful?
We could now implement behaviors that add new attributes to activerecords.
In my case i thought about implementing date/time/decimal conversion for i18n. My idea was to create a behavior that allows to prefix existing attributes with formatted (like formattedBirthday). These attributes could then be used for display purposes and maybe also to convert form input back into a generic format. They would behave much like "real" AR attributes.
But this is a different story …
Potential pitfals:
[b]
[/b]
I’m not sure how much sense it makes, to allow multiple listeners to attach. So maybe the above approach is already overdosed…
Please let me know your thoughts. The proposal is surely not perfect yet, but i think something similar would open up a wide range of possibilities.