我想在我的自定义MVC框架中实现一个Event系统,以允许解耦 需要互相交流的类。基本上,任何类触发事件的能力以及侦听此事件的任何其他类都能够挂钩它。
然而,鉴于php的性质没有任何架构,我似乎无法找到正确的实现。
例如,假设我有一个User模型,每次更新它时,它都会触发userUpdate事件。现在,此事件对于A类(例如)很有用,因为它需要在更新用户时应用自己的逻辑。 但是,更新用户时不会加载类A,因此它无法绑定到User对象触发的任何事件。
你怎么能绕过这种情况? 我错误地接近了吗?
非常感谢任何想法
答案 0 :(得分:5)
在触发事件之前必须有一个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
方法。如果你愿意,你也可以有一个抽象的事件类。
答案 1 :(得分:0)
我为自己做了一个非常简单的PHP Event Dispatcher / Event Hander,它是可测试的并且已在我的网站上使用过。
如果您需要,可以看看。