{"id":22764609,"url":"https://github.com/kuria/event","last_synced_at":"2025-04-14T23:13:35.990Z","repository":{"id":57009937,"uuid":"21098574","full_name":"kuria/event","owner":"kuria","description":"Event library that implements variations of the mediator and observer patterns","archived":false,"fork":false,"pushed_at":"2023-04-22T14:38:43.000Z","size":61,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-14T23:13:26.892Z","etag":null,"topics":["emitter","event-dispatcher","event-emitter","listeners","observable","observer","php","subscribers"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kuria.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-06-22T16:29:29.000Z","updated_at":"2023-09-19T17:45:33.000Z","dependencies_parsed_at":"2024-12-11T12:19:35.616Z","dependency_job_id":null,"html_url":"https://github.com/kuria/event","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuria%2Fevent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuria%2Fevent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuria%2Fevent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuria%2Fevent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kuria","download_url":"https://codeload.github.com/kuria/event/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248975328,"owners_count":21192210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emitter","event-dispatcher","event-emitter","listeners","observable","observer","php","subscribers"],"created_at":"2024-12-11T12:09:29.036Z","updated_at":"2025-04-14T23:13:35.963Z","avatar_url":"https://github.com/kuria.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Event\n#####\n\nEvent library that implements variations of the mediator and observer patterns.\n\n.. image:: https://travis-ci.com/kuria/event.svg?branch=master\n   :target: https://travis-ci.com/kuria/event\n\n.. contents::\n   :depth: 2\n\n\nFeatures\n********\n\n- emitting events with any number of arguments\n- managing listeners for specific or all events\n- ordering listeners by priority\n- stopping event propagation\n- multiple ways to embed the event system\n\n\nRequirements\n************\n\n- PHP 7.1+\n\n\nComponents\n**********\n\nEvent emitter\n=============\n\nThe ``EventEmitter`` class maintains a list of listeners and dispatches events\nto them.\n\nIt is intended to be used as a mediator.\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\EventEmitter;\n\n   $emitter = new EventEmitter();\n\n``EventEmitter`` implements ``ObservableInterface``.\n\n\nObservable\n==========\n\nThe abstract ``Observable`` class implements the ``ObservableInterface`` using\nan inner event emitter.\n\nIt is intended to be extended by child classes that will emit their own events:\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\Observable;\n\n   class MyComponent extends Observable\n   {\n       function doSomething()\n       {\n           $this-\u003eemit('something');\n       }\n   }\n\nAlternatively, you can use the ``ObservableTrait`` to achieve the same result:\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\EventEmitterPropInterface;\n   use Kuria\\Event\\ObservableInterface;\n   use Kuria\\Event\\ObservableTrait;\n\n   class MyComponent implements ObservableInterface, EventEmitterPropInterface\n   {\n       use ObservableTrait;\n\n       // ...\n   }\n\n\nUsage\n*****\n\nThe following applies to both `event emitter`_ and `observable`_ as they\nboth implement the ``ObservableInterface``.\n\n\nListening to events\n===================\n\nUsing a callback\n----------------\n\nTo register a callback to be called when a specific event occurs, register it\nusing the ``on()`` method. Any event arguments will be passed directly to it.\n\n.. code:: php\n\n   \u003c?php\n\n   $observable-\u003eon('some.event', function ($arg1, $arg2) {\n       // do something\n   });\n\n- the callback can stop event propagation by returning ``FALSE``\n- `listener priority`_ can be specified using the 3rd argument of ``on()``\n\nTo unregister a callback, call the ``off()`` method with the same callback\n(in case of closures this means the same object):\n\n.. code:: php\n\n   \u003c?php\n\n   $observable-\u003eoff('some.event', $callback); // returns TRUE on success\n\n\nUsing an event listener\n-----------------------\n\nTo register an event listener, use the ``addListener()`` method:\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\EventListener;\n\n   $observable-\u003eaddListener(\n       new EventListener(\n           'some.event',\n           function ($arg1, $arg2) {}\n       )\n   );\n\n- `listener priority`_ can be specified by using the 3rd argument of\n  the ``EventListener`` constructor\n- the callback can stop event propagation by returning ``FALSE``\n\nTo unregister a listener, call the ``removeListener()`` method with the same\nevent listener object:\n\n.. code:: php\n\n   \u003c?php\n\n   $observable-\u003eremoveListener($eventListener); // returns TRUE on success\n\n\nUsing an event subscriber\n-------------------------\n\nEvent subscribers subscribe to a list of events. Each event is usually mapped\nto one method of the subscriber.\n\nThe listeners can be created using the convenient ``listen()`` method\n(as shown in the example below) or by manually creating ``EventListener``\ninstances.\n\n- any callback or method can stop event propagation by returning ``FALSE``\n- `listener priority`_ can be specified using 3rd argument of ``listen()``\n  or the ``EventListener`` constructor\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\EventSubscriber;\n\n   class MySubscriber extends EventSubscriber\n   {\n       protected function getListeners(): array\n       {\n           return [\n               $this-\u003elisten('foo.bar', 'onFooBar'),\n               $this-\u003elisten('lorem.ipsum', 'onLoremIpsum', 10),\n               $this-\u003elisten('dolor.sit', 'onDolorSitA'),\n               $this-\u003elisten('dolor.sit', 'onDolorSitB', 5),\n           ];\n       }\n\n       function onFooBar() { /* do something */ }\n       function onLoremIpsum() { /* do something */ }\n       function onDolorSitA() { /* do something */ }\n       function onDolorSitB() { /* do something */ }\n   }\n\n   $subscriber = new MySubscriber();\n\n\nRegistering the event subscriber:\n\n.. code:: php\n\n   \u003c?php\n\n   $subscriber-\u003esubscribeTo($observable);\n\nUnregistering the event subsriber:\n\n.. code:: php\n\n   \u003c?php\n\n   $subscriber-\u003eunsubscribeFrom($observable);\n\n\nStopping event propagation\n--------------------------\n\nAny listener can stop further propagation of the current event by returning ``FALSE``.\n\nThis prevents any other listeners from being invoked.\n\n\nListener priority\n-----------------\n\nListener priority determines the order in which the listeners are invoked:\n\n- listeners with greater priority are invoked sooner\n- listeners with lesser priority are invoked later\n- if the priorities are equal, the order of invocation is undefined\n- priority can be negative\n- default priority is ``0``\n\n\nListening to all events\n=======================\n\nTo listen to all events, use ``ObservableInterface::ANY_EVENT`` in place\nof the event name:\n\n.. code:: php\n\n   \u003c?php\n\n   use Kuria\\Event\\EventListener;\n   use Kuria\\Event\\ObservableInterface;\n\n   $observable-\u003eon(\n       ObservableInterface::ANY_EVENT,\n       function ($event, $arg1, $arg2) {}\n   );\n\n   $observable-\u003eaddListener(\n       new EventListener(\n           ObservableInterface::ANY_EVENT,\n           function ($event, $arg1, $arg2) {}\n       )\n   );\n\n- global listeners are invoked before listeners of specific events\n- global listeners get an extra event name argument before the emitted\n  event arguments\n- global listeners can also stop event propagation by returning ``FALSE``\n  and may have specified `listener priority`_\n\n\nEmitting events\n===============\n\nEvents are emitted using the ``emit()`` method.\n\n.. code:: php\n\n   \u003c?php\n\n   $observable-\u003eemit('foo');\n\nAny extra arguments will be passed to the listeners.\n\n.. code:: php\n\n   \u003c?php\n\n   $observable-\u003eemit('foo', 'hello', 123);\n\n\n.. NOTE::\n\n   Variable references cannot be emitted directly as an argument. If you need to use\n   references, wrap them in an object or an array.\n\n\nDocumenting events\n==================\n\nWhile the event library itself doesn't require this, it is a good idea to explicitly define\npossible event names and their arguments somewhere.\n\nThe example below defines a ``FieldEvents`` class for this purpose. Constants of this class\nare then used in place of event names and their annotations serve as documentation. This also\nallows for code-completion.\n\n.. code:: php\n\n   \u003c?php\n   \n   use Kuria\\Event\\Observable;\n\n   /**\n    * @see Field\n    */\n   abstract class FieldEvents\n   {\n       /**\n        * Emitted when field value is about to be changed.\n        *\n        * @param Field $field\n        * @param mixed $oldValue\n        * @param mixed $newValue\n        */\n       const CHANGE = 'change';\n   \n       /**\n        * Emitted when field value is about to be cleared.\n        *\n        * @param Field $field\n        */\n       const CLEAR = 'clear';\n   }\n   \n   /**\n    * @see FieldEvents\n    */\n   class Field extends Observable\n   {\n       private $name;\n       private $value;\n   \n       function __construct(string $name, $value = null)\n       {\n           $this-\u003ename = $name;\n           $this-\u003evalue = $value;\n       }\n   \n       function getName(): string\n       {\n           return $this-\u003ename;\n       }\n   \n       function getValue()\n       {\n           return $this-\u003evalue;\n       }\n   \n       function setValue($value): void\n       {\n           $this-\u003eemit(FieldEvents::CHANGE, $this, $this-\u003evalue, $value);\n   \n           $this-\u003evalue = $value;\n       }\n   \n       function clear()\n       {\n           $this-\u003eemit(FieldEvents::CLEAR, $this);\n   \n           $this-\u003evalue = null;\n       }\n   }\n   \n.. NOTE::\n\n   Using ``@param`` annotations on class constants is non-standard, but IDE's dont mind\n   it and some documentation-generators (such as Doxygen) even display them nicely.\n\n\nUsage example\n-------------\n\n.. code:: php\n\n   \u003c?php\n  \n   $field = new Field('username');\n   \n   $field-\u003eon(FieldEvents::CHANGE, function (Field $field, $oldValue, $newValue) {\n       echo \"Field '{$field-\u003egetName()}' has been changed from '{$oldValue}' to '{$newValue}'\\n\";\n   });\n   \n   $field-\u003eon(FieldEvents::CLEAR, function (Field $field) {\n       echo \"Field '{$field-\u003egetName()}' has been cleared\\n\";\n   });\n   \n   $field-\u003esetValue('john.smith');\n   $field-\u003esetValue('foo.bar123');\n   $field-\u003eclear();\n\nOutput:\n\n::\n\n  Field 'username' has been changed from '' to 'john.smith'\n  Field 'username' has been changed from 'john.smith' to 'foo.bar123'\n  Field 'username' has been cleared\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuria%2Fevent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkuria%2Fevent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuria%2Fevent/lists"}