Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save stephanschuler/8ee13c017d7a141988474dc03b12885d to your computer and use it in GitHub Desktop.
Save stephanschuler/8ee13c017d7a141988474dc03b12885d to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
/*
* Event Dispatcher and Emitter are separate objects
* =================================================
*
* The dispatcher is meant to only receiver events:
* That's what the producing side holds.
*
* The emitter is meant for consumers to register.
*
* Variant:
* ========
*
* Pro:
* ----
*
* EventDispatcher::create() creates a EventDispatcher
*
* Con:
* ----
*
* EventEmitter::__emit() is public but "internal" annotated
*/
interface EventConsumer
{
public function consume($data): void;
}
class EventDispatcher /* implements \Psr\EventDispatcher\EventDispatcherInterface */
{
private $emitter;
private function __construct(EventEmitter $emitter)
{
$this->emitter = $emitter;
}
public static function create(): self
{
$emitter = new EventEmitter();
return new self($emitter);
}
public function dispatch($event): void
{
$this->emitter->__emit($event);
}
public function getEmitter(): EventEmitter
{
return $this->emitter;
}
}
class EventEmitter
{
protected $consumers = [];
public function __construct()
{
echo __METHOD__ . PHP_EOL;
}
public function __destruct()
{
echo __METHOD__ . PHP_EOL;
}
public function register(EventConsumer $consumer): void
{
$this->consumers[] = $consumer;
}
public function unregister(EventConsumer $consumer): void
{
$this->consumers = array_filter($this->consumers, function (EventConsumer $delinquent) use ($consumer) {
return $delinquent === $consumer;
});
}
/** @internal */
public function __emit($event): void
{
foreach ($this->consumers as $consumer) {
assert($consumer instanceof EventConsumer);
$consumer->consume($event);
}
}
}
echo 'Vorher' . PHP_EOL;
(function () {
$provider = EventDispatcher::create();
$emitter = $provider->getEmitter();
$emitter->register(new class implements EventConsumer {
public function consume($data): void
{
echo 'erstes: ' . $data . PHP_EOL;
}
});
$emitter->register(new class implements EventConsumer {
public function consume($data): void
{
echo 'zweites: ' . $data . PHP_EOL;
}
});
$provider->dispatch('xxx');
$provider->dispatch('yyy');
})
();
echo 'Nachher' . PHP_EOL;
<?php
declare(strict_types=1);
/*
* Event Dispatcher and Emitter are separate objects
* =================================================
*
* The dispatcher is meant to only receiver events:
* That's what the producing side holds.
*
* The emitter is meant for consumers to register.
*
* Variant:
* ========
*
* Pro:
* ----
*
* EventEmitter has no publicly accessible method to put events in
*
* Con:
* ----
*
* EventDispatcher::create() calls EventEmitter::createEventDispatcher()
* EventEmitter::createEventDispatcher() creates the EventDispatcher
* Clumsy anonymous function passed around
*/
interface EventConsumer
{
public function consume($data): void;
}
class EventDispatcher /* implements \Psr\EventDispatcher\EventDispatcherInterface */
{
private $emitter;
private $emitFunction;
public function __construct(EventEmitter $emitter, callable $emitFunction)
{
$this->emitter = $emitter;
$this->emitFunction = $emitFunction;
}
public static function create(): self
{
return EventEmitter::createEventDispatcher();
}
public function dispatch($event): void
{
($this->emitFunction)($event);
}
public function getEmitter(): EventEmitter
{
return $this->emitter;
}
}
class EventEmitter
{
protected $consumers = [];
public function __construct()
{
echo __METHOD__ . PHP_EOL;
}
public static function createEventDispatcher(): EventDispatcher
{
$emitter = new static();
$emitFunction = function ($event) use (&$emitter): void {
assert($emitter instanceof EventEmitter);
$emitter->__emit($event);
};
return new EventDispatcher($emitter, $emitFunction);
}
public function __destruct()
{
echo __METHOD__ . PHP_EOL;
}
public function register(EventConsumer $consumer): void
{
$this->consumers[] = $consumer;
}
public function unregister(EventConsumer $consumer): void
{
$this->consumers = array_filter($this->consumers, function (EventConsumer $delinquent) use ($consumer) {
return $delinquent === $consumer;
});
}
protected function __emit($event): void
{
foreach ($this->consumers as $consumer) {
assert($consumer instanceof EventConsumer);
$consumer->consume($event);
}
}
}
echo 'Vorher' . PHP_EOL;
(function () {
$provider = EventDispatcher::create();
$emitter = $provider->getEmitter();
$emitter->register(new class implements EventConsumer {
public function consume($data): void
{
echo 'erstes: ' . $data . PHP_EOL;
}
});
$emitter->register(new class implements EventConsumer {
public function consume($data): void
{
echo 'zweites: ' . $data . PHP_EOL;
}
});
$provider->dispatch('xxx');
$provider->dispatch('yyy');
})
();
echo 'Nachher' . PHP_EOL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment