Zend Framework 2 detach Listeners in ListenerAggregateInterface -
i implemented listeneraggregateinterface listening on dispatch (mvcevent::event_dispatch) event.
public function attach(eventmanagerinterface $events) { $this->listeners[] = $events->attach( mvcevent::event_dispatch, array($this, 'shortcircuit'), 101 ); $this->listeners[] = $events->attach( mvcevent::event_dispatch, array($this, 'listener1'), 33 ); $this->listeners[] = $events->attach( mvcevent::event_dispatch, array($this, 'listener2'), 33 ); } if status in shortciruit true rest of listeners should skipped. hence phone call listeneraggregateinterface::detach remove listeners.
public function shortcircuit(mvcevent $e) { if(condition) { $this->detach($e->getapplication()->geteventmanager()); } } i expecting not executed anymore, not case.
detaching listeners triggered event won't work while listeners beingness dispatched. because the listeners collected , sorted before executed in order sort them priority.
stopping propagation not work current approach, since want disable particular set of listeners.
there solution though, skip listeners when needed, using little registry record events skipped aggregate listener. wrote off top of head, it's un-tested, please unit test if want utilize it:
class="lang-php prettyprint-override">use splobjectstorage; utilize zend\eventmanager\eventinterface; final class skippedeventsregistry { /** @var splobjectstorage */ private $skippedevents; public function __construct() { $this->skippedevents = new splobjectstorage(); } /** * @param callable $callback * @return callable */ public function buildcallback(callable $callback) { homecoming function ($event) utilize ($callback) { if (isset($this->skippedevents[$event])) { return; } homecoming $callback($event); }; } public function skiplistenersforevent(eventinterface $event) { $this->skippedevents[$event] = $event; } public function restorelistenersforevent(eventinterface $event) { unset($this->skippedevents[$event]); } } then utilize registry within our aggregate listener:
class="lang-php prettyprint-override">use zend\eventmanager\eventinterface; utilize zend\eventmanager\eventmanagerinterface; utilize zend\eventmanager\listeneraggregateinterface; utilize zend\eventmanager\listeneraggregatetrait; class myaggregatelistener implements listeneraggregateinterface { utilize listeneraggregatetrait; private $skippedevents; public function __construct() { $this->skippedevents = new skippedeventsregistry(); } public function attach(eventmanagerinterface $events) { $this->listeners[] = $events->attach('someevent', $this->skippedevents->buildcallback(function ($event) { // ... other things here ... if ($worldisexploding) { // start skipping other listeners $this->skippedevents->skiplistenersforevent($event); } }), 9999); $this->listeners[] = $events->attach('someevent', $this->skippedevents->buildcallback(function ($event) { // ... other things here ... }), 8888); // reset normal execution // (sadly, happens if propagation wasn't stopped) $this->listeners[] = $events->attach( 'someevent', [$this->skippedevents, 'restorelistenersforevent'], -9999999999 ); } } (sorry alignment mess-up, it's quite hard fit within overflow :\ )
as can see, stopping listeners beingness executed when event marked "skipped" through registry. happens when $worldisexploding = true during first listener execution.
after that, execute other listeners , clean @ end through low-priority listener.
eventually, can phone call $this->skippedevents->restorelistenersforevent($event) in event listener high priority. prevents listeners beingness skipped if same $event instance used multiple zend\eventmanager\eventmanagerinterface#trigger() calls.
zend-framework2
No comments:
Post a Comment