我正在尝试用PHP创建类似CMS的系统。使其尽可能模块化和可扩展。
有人能为我提供在PHP中创建事件监听器系统的最佳实践场景(例如Drupal系统的一个非常简化的版本),创建钩子并在一个简短的例子中实现它们也会很好。
答案 0 :(得分:130)
嗯,从实现的角度来看,实际上有三种不同的方法(请注意,这些是OO设计模式,但如果您愿意,可以在功能上或程序上实现它们。)
<强> 1。观察者模式
您可以实施Observer Pattern。基本上,你可以将每件可以引发事件的东西都当作主题。然后,您想要监听的类/代码将特定地绑定到它想要听的内容。所以假设你有一个名为Foo
的控制器。如果您想听,可以致电$fooController->attach($observer);
。然后,每当控制器想要说些什么时,它就会将事件发送给所有观察者。
这非常适合通知系统(扩展正在进行的类)。它不太适合实时修改代码行为。
<强> 2。装饰者模式 您还可以实施Decorator Pattern。基本上,您获取要修改的对象,并将其“包装”在一个新对象中,该对象执行您想要更改的内容。这非常适合修改和扩展行为(因为您可以有选择地覆盖包装类中的功能)。
如果您已定义接口并期望对象符合它们,则此方法非常有效。如果你没有接口(或者没有正确使用它们),那么装饰器模式可以为你做的大部分都将丢失。
另请注意,这实际上不是一种做事件的方式,它是一种修改对象行为的方法。
第3。调解员模式
您还可以使用Mediator。基本上,你有一个全局调解员可以跟踪你的听众。如果要触发事件,请将事件发送给调解器。然后,介体可以跟踪哪些侦听对象想要接收该事件,并正确传递消息。
这具有中心优势。这意味着多个发件人可以发送相同的事件,并且对于听众而言,发送它的人并没有什么不同......
答案 1 :(得分:33)
/*
Example 1:
event::bind('blog.post.create', function($args = array())
{
mail('myself@me.com', 'Blog Post Published', $args['name'] . ' has been published');
});
Example 2:
event::trigger('blog.post.create', $postInfo);
*/
class event
{
public static $events = array();
public static function trigger($event, $args = array())
{
if(isset(self::$events[$event]))
{
foreach(self::$events[$event] as $func)
{
call_user_func($func, $args);
}
}
}
public static function bind($event, Closure $func)
{
self::$events[$event][] = $func;
}
}
答案 2 :(得分:13)
这就是我在几个项目中的表现
所有对象都是使用构造函数而不是new
运算符创建的。
$obj = _new('SomeClass', $x, $y); // instead of $obj = new SomeClass($x, $y);
与原始new
相比,这有许多优点,从事件处理的角度来看,_new()
维护所有已创建对象的列表非常重要。
还有一个全局函数send($message, $params)
迭代此列表,如果一个对象公开一个方法“on_ $ message”,则调用此方法,传递params:
function send() {
$_ = func_get_args();
$m = "on_" . array_shift($_);
foreach($_all_objects as $obj)
if(method_exists($obj, $m))
call_user_func_array(array($obj, $m), $_);
}
因此,例如,send('load')
将为每个已定义的对象调用on_load
方法。
答案 3 :(得分:4)