I have a simple "works-for-me" event driven framework. Some examples:
Code: Select all
interface IObservable
{
public function hasEvent($event);
public function hasEventAlias($event);
public function getEventAlias($event);
public function getEvents();
public function fireEvent($event, &$data = null);
public function on($class, $event, $method);
}
class BadEventFireException extends Exception {}
class BadEventCallbackException extends Exception {}
class BadEventAliasException extends Exception {}
Code: Select all
class Collection_Model extends Module_Model // Module_Model implements IObservable
{
protected $events = array
(
'initialize',
'beforeGetDql',
'getResult',
'getRecord',
'getResponseRecord',
'beforeRawChange',
'beforeRecordChange',
'afterRecordChange',
'getAfterChange',
'beforeRawAdd' => array('beforeRawChange'),
'beforeRecordAdd' => array('beforeRecordChange'),
'afterRecordAdd' => array('afterRecordChange'),
'getAfterAdd' => array('getAfterChange'),
'beforeRawSave' => array('beforeRawChange'),
'beforeRecordSave' => array('beforeRecordChange'),
'afterRecordSave' => array('afterRecordChange'),
'getAfterSave' => array('getAfterChange'),
'beforeRawUpdate' => array('beforeRawChange'),
'beforeRecordUpdate'=> array('beforeRecordChange'),
'afterRecordUpdate' => array('afterRecordChange'),
'getAfterUpdate' => array('getAfterChange'),
'beforeRawRemove',
'beforeRecordRemove',
'afterRecordRemove',
'getAfterRemove',
);
....
/**
* Remove an object from the collection
*
* @access public
* @return Array
*/
public function remove($data)
{
try
{
Doctrine_Manager::connection()->beginTransaction();
if ($this->fireEvent('beforeRawRemove', $data) !== false)
{
$this->record = $this->createFromObject($data);
if ($this->fireEvent('beforeRecordRemove', $this->record, $data) !== false)
{
$this->record->delete();
$this->fireEvent('afterRecordRemove', $this->record, $data);
if ($this->fireEvent('getResponseRecord', $this->record) === false)
{
return array('response' => null);
}
$data = $this->prepareEventData($this->record->toArray(true));
if ($this->fireEvent('getAfterRemove', $data) !== false)
{
Doctrine_Manager::connection()->commit();
return array
(
'response' => $data
);
}
else
{
Doctrine_Manager::connection()->rollback();
return array();
}
}
else
{
Doctrine_Manager::connection()->rollback();
return array();
}
}
else
{
Doctrine_Manager::connection()->rollback();
return array();
}
}
catch (Exception $E)
{
Doctrine_Manager::connection()->rollback();
Error::register($E->getMessage());
}
}
...
}
Code: Select all
class User_Collection_Model extends Collection_Model
{
protected function hook()
{
parent::hook();
$this->on('User_Collection_Model', 'beforeRecordRemove', 'onBeforeUserRemove');
}
public function onBeforeUserRemove($sender, &$record)
{
if ($record->id === $this->currentUser->getId())
{
Error::register('Can not remove current user.');
return false;
}
}
}You can see events are not fired per class instance, but per classes (which is fine to me for now). I think it might be problem with my implementation, but I'm very happy with it in my current design - a pluggable and modular system. This way my new plugins/modules (which are Models indeed, so they are single-instance ones) doesn't need an concrete object instance in order to observe it. It even doesn't have to be there (i.e. observing non installed modules)
So, what do you think?
PS: I could do something like:
Code: Select all
$this->for->User_Collection_Model->on->beforeRecordRemove->do->onBeforeUserRemove;