PHP事件系统实现

4
我想在我的自定义MVC框架中实现事件系统,以允许需要相互交互的类解耦。基本上,任何类都可以触发事件,任何监听此事件的其他类都可以连接到它。
然而,考虑到php的“共享无”架构,我似乎找不到正确的实现方式。
例如,假设我有一个用户模型,每次更新用户时,它会触发一个userUpdate事件。现在,对于A类(例如),这个事件很有用,因为当用户被更新时,它需要应用自己的逻辑。然而,在用户被更新时,A类没有加载,因此它无法绑定到由User对象触发的任何事件。
如何解决这种情况? 我的方法是否正确?
任何想法将不胜感激。

嗯,把事件绑定处理放到控制器里会更好吧? - BenM
为什么不能提前加载A类?应该有某种逻辑能够意识到用户模型将被使用,因此其他组件需要与之连接。我也不确定你为什么提到了共享无状态架构。 - goat
1
你是否咨询过观察者/可观察设计模式?http://www.sitepoint.com/understanding-the-observer-pattern/ - Ma'moon Al-Akash
嗨,谢谢你提供的链接,我会去看一下。 - Thomas
如果您想要实现观察者模式,请查看SplObserver接口SplSubject接口 - bitWorking
2个回答

6

在触发事件之前,必须有一个A类的实例,因为您必须注册该事件。唯一的例外是如果您注册了一个静态方法。

假设您有一个用户类应该触发一个事件。首先,您需要一个(抽象)事件分派器类。这种事件系统的工作方式类似于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]));
    }
}

您的用户类现在可以扩展该调度程序:

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类。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接