phossa2 / event
PSR-14 event manager implementation libraray for PHP
Installs: 170 373
Dependents: 3
Suggesters: 0
Security: 0
Stars: 10
Watchers: 4
Forks: 2
Open Issues: 0
This package is not auto-updated.
Last update: 2020-01-24 16:22:48 UTC
README
PLEASE USE phoole/event library instead
phossa2/event is a PSR-14 event manager library for PHP.
It requires PHP 5.4, supports PHP 7.0+ and HHVM. It is compliant with PSR-1, PSR-2, PSR-4 and the upcoming PSR-14
Installation
Install via the composer
utility.
composer require "phossa2/event=2.1.*"
or add the following lines to your composer.json
{ "require": { "phossa2/event": "^2.1.0" } }
Features
-
Event name globbing.
-
Built-in multiple shared event managers support.
-
Attach and detach listeners.
-
Static event manager support.
-
Built-in class level events support.
-
Able to limit number of times of an event callable executed.
Usage
-
use Phossa2\Event\EventDispatcher; // event dispatcher $events = new EventDispatcher(); // bind event with a callback $events->attach('login.success', function($evt) { echo "logged in as ". $evt->getParam('username'); }); // bind event with a callable $events->attach('login.attempt', [$logger, 'logEvent']); // unbind an event $events->clearListeners('login.attempt'); // fire the trigger $events->trigger('login.success');
-
Event name globbing means callables of the binding 'login.*' will also be triggered when triggering event 'login.success'.
// bind 'login.*' with callables $events->attach('login.*', function($evt) { echo $evt->getName(); }); // trigger 'login.atttempt' will also trigger callables of 'login.*' $events->trigger('login.attempt');
The globbing rules are similiar to the PHP function
glob()
, where-
*
in the string means any chars except the dot. -
If
*
at the end, will match any chars including the dot. e.g.login.*
will match 'login.attempt.before'. -
.
means the dot. -
one-char-string
*
means match any string (including the dot).
Note: Name globbing ONLY happens when event is being triggered. Binding or unbinding events only affect the EXACT event name.
// unbind the exact 'login.*' $events->clearListeners('login.*');
-
-
Class
EventDispatcher
implements thePhossa2\Shared\Shareable\ShareableInterface
.ShareableInterface
is an extended version of singleton pattern. Instead of supporting only one shared instance, Classes implementsShareableInterface
may have shared instance for differentscope
.// global event manager, global scope is '' $globalEvents = EventDispatcher::getShareable(); // shared event manager in scope 'MVC' $mvcEvents = EventDispatcher::getShareable('MVC'); // an event manager instance, which has scope 'MVC' $events = new EventDispatcher('MVC'); // in scope MVC ? var_dump($events->hasScope('MVC')); // true // in global scope ? var_dump($events->hasScope()); // true
Callables bound to a shared manager will also be triggered if an event manager instance has the same scope.
// shared event manager in scope 'MVC' $mvcEvents = EventDispatcher::getShareable('MVC'); // bind with pirority 100 (highest priority) $mvcEvents->attach('*', function($evt) { echo "mvc"; }, 100); // create a new instance within the MVC scope $events = new EventDispatcher('MVC'); // bind with default priority 0 $events->attach('test', function($evt) { echo "test"; }); // will also trigger matched events in $mvcEvents $events->trigger("test");
Event manager instance can have multiple scopes, either specified during the instantiation or using
addScope()
.// create an event manager with 2 scopes $events = new EventDispatcher(['MVC', 'AnotherScope']); // add another scope $events->addScope('thirdScope');
Couple of helper methods are provided for on/off/trigger events with shared managers.
// bind a callable to global event manager EventDispatcher::onGlobalEvent('login.success', function() {}); // use interface name as a scope EventDispatcher::onEvent( 'Psr\\Log\\LoggerInterface', // scope 'log.error', // event name function () {} ); // unbind all callables of event 'log.error' in a scope EventDispatcher::offEvent( 'Psr\\Log\\LoggerInterface', 'log.error' ); // unbind *ALL* events in global scope EventDispatcher::offGlobalEvent();
-
Listener
implements theListenerInterface
. Or in short, provides a methodeventsListening()
.use Phossa2\Event\Interfaces\ListenerInterface; class myListener implements ListenerInterface { public function eventsListening() { return [ // one method of $this eventName1 => 'method1', // 2 methods eventName2 => ['callable1', 'method2'], // priority 20 and in a 'mvcScope' scope eventName2 => ['method2', 20, 'mvcScope'], // with priority 20 eventName3 => [ ['method3', 50], ['method4', 70, 'anotherScope'] ] ]; } }
EventDispatcher::attachListener()
can be used to bind events defined ineventsListening()
instead of usingEventDispatcher::attach()
to bind each event manually.$events = new EventDispatcher(); $listener = new \myListener(); // bind all events defined in $listener->eventsListening() $events->attachListener($listener); // will call $listener->method1() $events->trigger('eventName1');
-
Using event manager statically
StaticEventDispatcher
is a static wrapper for anEventDispatcher
slave.StaticEventDispatcher::attach('*', function($evt) { echo 'event ' . $evt->getName(); }); // will print 'event test' StaticEventDispatcher::trigger('test');
StaticEventDispatcher
is not the same as global event manager.StaticEventDispatcher
has a default slave which is a shared event manager in scope'__STATIC__'
. While global event manager is the shared event manager in global scope''
.User may set another event manager to replace the default slave.
StaticEventDispatcher::setEventManager(new EventDispatcher());
-
EventCapableAbstract
EventCapableAbstract
implements bothListenerInterface
andEventCapableInterface
. It will do the following whentriggerEvent()
is called,-
Get the event manager. If it is not set yet, create one default event manager with current classname as scope.
-
Attach events defined in
eventsListening()
if not yet. -
Trigger the event and processed by the event manager and all of the shared managers of its scopes.
class LoginController extends EventCapableAbstract { public function login() { // failed if (!$this->trigger('login.pre')) { return; } // ... } public function beforeLogin() { // ... } public function eventsListening() { return [ 'login.pre' => 'beforeLogin' ]; } }
-
-
EventableExtensionAbstract
andEventableExtensionCapableAbstract
EventableExtensionCapableAbstract
is the base class supporting events and extensions.Detail usage can be found in phossa2/cache
Phossa2\Cache\CachePool
extendsEventableExtensionCapableAbstract
andPhossa2\Cache\Extension\ByPass
extendsEventableExtensionAbstract
.Or look at phossa2/route.
-
Class or interface level events support
Class or interface name can be used as the
scope
. When events bound to these kind of scopes, any events triggered by child class will also search callables defined in parent class/interface level shared event managers.// define event '*' for interface 'MyInterface' EventDispatcher::onEvent( 'MyInterface', '*', function() { echo "MyInterface"; }, 60 );
Extends
EventCapableAbstract
.class MyClass extends EventCapableAbstract implements MyInterface { public function myMethod() { echo "myMethod"; } public function eventsListening()/*# : array */ { return [ // priority 20 'afterTest' => ['myMethod', 20] ]; } } $obj = new MyClass(); // will trigger callable 'myMethod' and handlers for 'MyInterface' $obj->trigger('afterTest');
-
Execute callable for limited times
// bind a callable for executing only once $events->one('user.login', function(Event $evt) { // ... }); // 3 times $events->many(3, 'user.tag', function(Event $evt) { // ... });
Change log
Please see CHANGELOG from more information.
Testing
$ composer test
Contributing
Please see CONTRIBUTE for more information.
Dependencies
-
PHP >= 5.4.0
-
phossa2/shared >= 2.0.21