Laravel Event模块分析
事件模块是一个由四个静态数组构成的部件,存在于内存中,提供事件模拟。
<?php namespace Laravel; class Event { /** * 所有注册的事件 * * @var array */ public static $events = array(); /** * 队列事件 等待flush * * @var array */ public static $queued = array(); /** * 队列flush之后回调 * * @var array */ public static $flushers = array(); /** * 注册事件是否有回调 * * @param string $event * @return bool */ public static function listeners($event) { return isset(static::$events[$event]); } /** * 注册事件回调 * * <code> * // "start" 事件 * Event::listen('start', function() {return 'Started!';}); * * // 注册对象实例方法回调 * Event::listen('event', array($object, 'method')); * </code> * * @param string $event * @param mixed $callback * @return void */ public static function listen($event, $callback) { static::$events[$event][] = $callback; # 数据格式 [$event] array $object,methodName } /** * 给定事件重写所有回调 * * @param string $event * @param mixed $callback * @return void */ public static function override($event, $callback) { static::clear($event); static::listen($event, $callback); } /** * 队列增加数据 * * @param string $queue * @param string $key * @param mixed $data * @return void */ public static function queue($queue, $key, $data = array()) { static::$queued[$queue][$key] = $data; } /** * 注册队列执行回调 * * @param string $queue * @param mixed $callback * @return void */ public static function flusher($queue, $callback) { static::$flushers[$queue][] = $callback; } /** * 清楚所给事件回调 * * @param string $event * @return void */ public static function clear($event) { unset(static::$events[$event]); } /** * 触发事件 返回第一值 * * <code> * // Fire the "start" event * $response = Event::first('start'); * * // Fire the "start" event passing an array of parameters * $response = Event::first('start', array('Laravel', 'Framework')); * </code> * * @param string $event * @param array $parameters * @return mixed */ public static function first($event, $parameters = array()) { return head(static::fire($event, $parameters)); # 执行所有回调 但只提取第一值 } /** * 触发事件返回第一个值 * * 第一个值返回之后执行被挂起 * * @param string $event * @param array $parameters * @return mixed */ public static function until($event, $parameters = array()) { return static::fire($event, $parameters, true); # 未执行所有回调 只执行第一值 } /** * 刷新事件多列, 触发每个占位 * * @param string $queue * @return void */ public static function flush($queue) { foreach (static::$flushers[$queue] as $flusher) { if ( ! isset(static::$queued[$queue])) continue; foreach (static::$queued[$queue] as $key => $payload) { array_unshift($payload, $key); # 调整参数 call_user_func_array($flusher, $payload); # 调用 } } } /** * 触发事件所有监听器 * * <code> * // "start" 事件 * $responses = Event::fire('start'); * * // "start" 事件参数 * $responses = Event::fire('start', array('Laravel', 'Framework')); * * // 同一参数触发多个事件 * $responses = Event::fire(array('start', 'loading'), $parameters); * </code> * * @param string|array $events * @param array $parameters * @param bool $halt * @return array */ public static function fire($events, $parameters = array(), $halt = false) { $responses = array(); $parameters = (array) $parameters; # 参数是array // 遍历触发 返回结果集 foreach ((array) $events as $event) { if (static::listeners($event)) { foreach (static::$events[$event] as $callback) # 遍历监听器 { $response = call_user_func_array($callback, $parameters); # 实例方法触发原因:call_user_func_array 换成反射就能提供更多方式 换成Ding更好 // 第一值返回挂起 if ($halt and ! is_null($response)) { return $response; } // 结果集 $responses[] = $response; } } } return $halt ? null : $responses; # 挂起标记 } }
只提供模拟,不支持数据化,不支持分布式。
不过够简单,简洁就是美丽。
就理解上来说,事件模块可以被其他所有模块调用,但是需要安排好唯一标识,防止覆写。