foo.bar.baz
).some.event
another.event
yet.another.event
something.new
on()
, one()
, off()
, trigger()
. I liked this approach mostly because of their brevity and brevity. Dispatcher { public Dispatcher on(string $event, callable $listener) public Dispatcher once(string $event, callable $listener) public Dispatcher off([string $event [, callable $listener ]]) public Dispatcher trigger(string $event [, array $args ]) public Dispatcher fire(string $event [, array $args ]) }
off()
method can take two parameters, and then the specific handler of the specified event will be deleted. One parameter - in this case all event handlers will be deleted. Or do not take any parameters, which means deleting all events and handlers subscribed to them.trigger()
accepts an event key template, and spawns all matching events.fire()
in turn, generates one specifically specified event.once()
method namespace Yowsa\Eventable; class Dispatcher { protected $events = []; public function on($event, callable $listener) { if (!KeysResolver::isValidKey($event)) { throw new \InvalidArgumentException('Invalid event name given'); } if (!isset($this->events[$event])) { $this->events[$event] = []; } $this->events[$event][] = $listener; return $this; } public function once($event, callable $listener) { $onceClosure = function () use (&$onceClosure, $event, $listener) { $this->off($event, $onceClosure); call_user_func_array($listener, func_get_args()); }; $this->on($event, $onceClosure); return $this; } public function off($event = null, callable $listener = null) { if (empty($event)) { $this->events = []; } elseif (empty($listener)) { $this->events[$event] = []; } elseif (!empty($this->events[$event])) { $index = array_search($listener, $this->events[$event], true); if (false !== $index) { unset($this->events[$event][$index]); } } return $this; } public function trigger($event, array $args = []) { $matchedEvents = KeysResolver::filterKeys($event, array_keys($this->events)); if (!empty($matchedEvents)) { if (is_array($matchedEvents)) { foreach ($matchedEvents as $eventName) { $this->fire($eventName, $args); } } else { $this->fire($matchedEvents, $args); } } return $this; } public function fire($event, array $args = []) { foreach ($this->events[$event] as $listener) { call_user_func_array($listener, $args); } return $this; } }
*
- one segment, up to the separator;**
- any number of segments.application.user.signin.error
key, you can create the following valid patterns:application.**.error
**.error
application.user.*.error
application.user.**
KeysResolver { public static int isValidKey(string $key) public static string getKeyRegexPattern(string $key) public static mixed filterKeys(string $pattern [, array $keys ]) }
namespace Yowsa\Eventable; class KeysResolver { public static function isValidKey($key) { return preg_match('/^(([\w\d\-]+)\.?)+[^\.]$/', $key); } public static function getKeyRegexPattern($key) { $pattern = ('*' === $key) ? '([^\.]+)' : (('**' === $key) ? '(.*)' : str_replace( array('\*\*', '\*'), array('(.+)', '([^.]*)'), preg_quote($key) ) ); return '/^' . $pattern . '$/i'; } public static function filterKeys($pattern, array $keys = array()) { $matched = preg_grep(self::getKeyRegexPattern($pattern), $keys); if (empty($matched)) { return null; } if (1 === count($matched)) { return array_shift($matched); } return array_values($matched); } }
require_once __DIR__ . '/../vendor/autoload.php'; $dispatcher = new Yowsa\Eventable\Dispatcher(); $teacher = 'Mrs. Teacher'; $children = ['Mildred', 'Nicholas', 'Kevin', 'Bobby', 'Anna', 'Kelly', 'Howard', 'Christopher', 'Maria', 'Alan']; // teacher comes in the classroom // and children welcome her once $dispatcher->once('teacher.comes', function($teacher) use ($children) { foreach ($children as $kid) { printf("%-12s- Hello, %s!\n", $kid, $teacher); } }); // every kid answers to teacher once foreach ($children as $kid) { $dispatcher->once("children.{$kid}.says", function() use ($kid) { echo "Hi {$kid}!\n"; }); } // boddy cannot stop to talk $dispatcher->on('children.Bobby.says', function() { echo "\tBobby: I want pee\n"; }); // trigger events echo "{$teacher} is entering the classroom.\n\n"; $dispatcher->trigger('teacher.comes', [$teacher]); echo "\n\n{$teacher} welcomes everyone personally\n\n"; $dispatcher->trigger('children.*.says'); for ($i = 0; $i < 5; $i++) { $dispatcher->trigger('children.Bobby.says'); }
Mrs. Teacher is entering the classroom. Mildred β Hello, Mrs. Teacher! Nicholas β Hello, Mrs. Teacher! Kevin β Hello, Mrs. Teacher! Bobby β Hello, Mrs. Teacher! Anna β Hello, Mrs. Teacher! Kelly β Hello, Mrs. Teacher! Howard β Hello, Mrs. Teacher! Christopher β Hello, Mrs. Teacher! Maria β Hello, Mrs. Teacher! Alan β Hello, Mrs. Teacher! Mrs. Teacher welcomes everyone personally Hi Mildred! Hi Nicholas! Hi Kevin! Hi Bobby! Bobby: I want pee Hi Anna! Hi Kelly! Hi Howard! Hi Christopher! Hi Maria! Hi Alan! Bobby: I want pee Bobby: I want pee Bobby: I want pee Bobby: I want pee Bobby: I want pee
Source: https://habr.com/ru/post/202234/
All Articles