我想在我的自定义MVC框架中实现一个事件系统,以允许解耦需要相互交互的类。基本上,任何类触发事件的能力,以及任何其他侦听该事件的类能够挂接该事件的能力
然而,考虑到php的sharenothing架构的性质,我似乎找不到正确的实现。
例如,假设我有一个用户模型,每次更新它时,它都会触发一个userUpdate事件。现在,这个事件对类A很有用(例如),因为它需要在更新用户时应用自己的逻辑。但是,在更新用户时不会加载类A,因此它无法绑定到user对象触发的任何事件。
你怎么能避开这种情况?我是不是搞错了?
任何想法都将不胜感激
在触发事件之前必须有一个类A的实例,因为您必须注册该事件。如果您注册了一个静态方法,则会出现一个例外。
假设您有一个User类,它应该触发一个事件。首先,您需要一个(抽象的)事件调度程序类。这种事件系统的工作方式类似ActionScript3:
abstract class Dispatcher
{
protected $_listeners = array();
public function addEventListener($type, callable $listener)
{
// fill $_listeners array
$this->_listeners[$type][] = $listener;
}
public function dispatchEvent(Event $event)
{
// call all listeners and send the event to the callable's
if ($this->hasEventListener($event->getType())) {
$listeners = $this->_listeners[$event->getType()];
foreach ($listeners as $callable) {
call_user_func($callable, $event);
}
}
}
public function hasEventListener($type)
{
return (isset($this->_listeners[$type]));
}
}
您的User类现在可以扩展Dispatcher:
class User extends Dispatcher
{
function update()
{
// do your update logic
// trigger the event
$this->dispatchEvent(new Event('User_update'));
}
}
如何注册该活动?假设您有方法为update
的类A。
// non static method
$classA = new A();
$user = new User();
$user->addEventListener('User_update', array($classA, 'update'));
// the method update is static
$user = new User();
$user->addEventListener('User_update', array('A', 'update'));
如果您有适当的自动加载,则可以调用静态方法。在这两种情况下,Event
都将作为参数发送给update
方法。如果你喜欢的话,你也可以有一个抽象的Event类。
我为自己制作了一个非常简单的PHP事件调度程序/事件处理程序,它是可测试的,并已在我的网站上使用。
如果你需要,你可以看看。