PHP中的事件驱动架构和钩子


Event-driven architecture and hooks in PHP

我计划在一个有PHP后端与数据存储库通信的游戏上工作。我仔细思考后得出结论,我们游戏的最佳设计范例应该是事件驱动。我希望拥有一个成就系统(类似于这个网站的徽章系统),基本上我希望能够将这些"成就检查"挂钩到游戏中发生的许多不同事件中。即:

当用户执行操作X时,钩子Y被触发,并调用所有附加的函数来检查是否符合成就要求。

在构建这样的架构时,我将允许很容易地添加新的成就,因为我所要做的就是将检查功能添加到适当的钩子中,其他一切都将就位。

我不确定这是否是一个很好的解释我打算做什么,但无论如何,我正在寻找以下内容:

  1. 关于如何编写事件驱动应用程序的良好参考资料
  2. 显示如何在PHP函数中放置"hook"的代码片段
  3. 显示如何将函数附加到第2点提到的"钩子"上的代码片段

我对如何完成2)和3)有一些想法,但我希望有精通这方面的人能给我一些最佳做法的启示。

提前感谢!

关于如何编写事件驱动应用程序的良好参考资料

你可以使用"dumb"回调(Demo):

class Hooks
{
    private $hooks;
    public function __construct()
    {
        $this->hooks = array();
    }
    public function add($name, $callback) {
        // callback parameters must be at least syntactically
        // correct when added.
        if (!is_callable($callback, true))
        {
            throw new InvalidArgumentException(sprintf('Invalid callback: %s.', print_r($callback, true)));
        }
        $this->hooks[$name][] = $callback;
    }
    public function getCallbacks($name)
    {
        return isset($this->hooks[$name]) ? $this->hooks[$name] : array();
    }
    public function fire($name)
    {
        foreach($this->getCallbacks($name) as $callback)
        {
            // prevent fatal errors, do your own warning or
            // exception here as you need it.
            if (!is_callable($callback))
                continue;
            call_user_func($callback);
        }
    }
}
$hooks = new Hooks;
$hooks->add('event', function() {echo 'morally disputed.';});
$hooks->add('event', function() {echo 'explicitly called.';});
$hooks->fire('event');

或者实现事件驱动应用程序中经常使用的模式:观察者模式

显示如何在PHP函数中放置"hook"的代码片段

上面的手动链接(回调可以存储到一个变量中)和一些用于观察者模式的PHP代码示例

对于PHP,我经常集成Symfony事件组件:http://components.symfony-project.org/event-dispatcher/.

下面是一个简短的例子,你可以在Symfony的Recipe部分找到扩展。

<?php
class Foo
{
  protected $dispatcher = null;
    // Inject the dispatcher via the constructor
  public function __construct(sfEventDispatcher $dispatcher)
  {
    $this->dispatcher = $dispatcher;
  }
  public function sendEvent($foo, $bar)
  {
    // Send an event
    $event = new sfEvent($this, 'foo.eventName', array('foo' => $foo, 'bar' => $bar));
    $this->dispatcher->notify($event);
  }
}

class Bar
{
  public function addBarMethodToFoo(sfEvent $event)
  {
    // respond to event here.
  }
}

// Somewhere, wire up the Foo event to the Bar listener
$dispatcher->connect('foo.eventName', array($bar, 'addBarMethodToFoo'));
?>

这是我们整合到购物车中的系统,以创造游戏般的购物体验,将用户行为与游戏事件联系起来。当用户执行特定的操作时,php会触发事件,从而触发奖励。

示例1:如果用户点击一个特定的按钮10次,他们会收到一个星星。

示例2:当用户推荐一个朋友并且该朋友注册时,将触发一个事件,奖励原始推荐人点数。

查看CodeIgniter,因为它内置了钩子。

简单地启用钩子:

$config['enable_hooks'] = TRUE;

然后定义钩子:

 $hook['post_controller_constructor'] = array(
                                'class'    => 'Hooks',
                                'function' => 'session_check',
                                'filename' => 'hooks.php',
                                'filepath' => 'hooks',
                                'params'   => array()
                                ); 

然后在你的类中使用它:

<?php
    class Hooks {
        var $CI;
        function Hooks() {
            $this->CI =& get_instance();
        }
        function session_check() {
            if(!$this->CI->session->userdata("logged_in") && $this->CI->uri->uri_string != "/user/login")
                redirect('user/login', 'location');
        }
    }
?>