Simuland Evenimente in PHP
0Evenimente
Evenimentele permit unei clase sau obiect sa emita o notificare altei clase sau obiecte cand ceva care ne intereseaza apare. Clasa care trimite evenimentul se numeste dispatcher (emitator) iar clasa care receptioneaza evenimentul se numeste event listener (receptor)
Una din cele mai mare dezavantaje al php’ului este lipsa de evenimente, insa un framework de baza poate fi construit pentru a simula evenimente.
Clasa Event
Primul lucru pe care o sa il cream va fi un simplu obiect care va retine numele si callback’ul ( functia pe care o va chema cand evenimentul este declansat ), infasurand aceste elemente intr’o clasa ne va permite mai tarziu sa extindem clasa si sa construim evenimente din ce in ce mai complexe. Clasa Object este acolo doar pentru a furniza o implementare de baza a functiei __toString().
abstract class Object { public function __toString() { return '[object ' . get_class($this) . ']'; } } class Event extends Object { protected $name; protected $callback; public function __construct($event_name, $callback = null) { if($event_name === null) throw new Exception('Event class must have a name.'); else if($callback !== null) $this -> callback = $callback; $this -> name = $event_name; } public function setCallback($callback) { $this -> callback = $callback; } public function getCallback() { return $this -> callback; } public function getSender() { return $this -> callback[0]; } public function getName() { return $this -> name; } }
Clasa EventCollection
Inauntru clasei EventCollection vom retine evenimentele si vom putea face operatii de baza pe aceastea adaugare, verificare si stergere. Interfetele SeekableIterator si Countable ne va permite sa utilizam functiile count() si foreach() asupra clasei EventCollection.
class EventCollection extends Object implements SeekableIterator, Countable { private $events; public function __construct() { $this -> events = array(); } public function addEvent(Event $eventObject) { if(!$this -> contains($eventObject -> getName())) $this -> events[] = $eventObject; } public function contains($event_name) { foreach($this -> events as $event) if($event -> getName() === $event_name) return true; return false; } public function removeEvent(Event $event) { for($i = 0; $i < count($events); $i++) if($this -> events[$i] -> getName() === $event_name -> getName()) array_splice($this -> events, $i, 1); } public function seek($position) { if($position >= count($this -> events)) throw new OutOfBoundsException("invalid seek position ($position)"); $this -> rewind(); for($i = 0; $i <= $position; $i++) next(); } public function count() { return count($this -> events); } public function rewind() { reset($this -> events); } public function current(){ return current($this -> events); } public function key() { key($this -> events); } public function next() { return next($this -> events); } public function valid() { return ($this -> current() !== false); } }
Clasa EventDispatcher
Pana acuma avem o clasa Event si o clasa care ne va permite sa facem operatii de baza asupra evenimentelor insa o sa avem nevoie de o metoda de a anunta si asculta asupra evenimentelor unei clase. Clasa EventDispatcher va fi clasa de baza care va trebui sa fie mostenita pentru a ii se acesa metodele.
class EventDispatcher extends Object { protected $events; protected function dispatchEvent(Event $event) { if(!($this -> events instanceof EventCollection)) $this -> events = new EventCollection(); foreach($this -> events as $e) if($e -> getName() === $event -> getName()) if(is_callable($e -> getCallback())) call_user_func($e -> getCallback(), $event); else throw new Exception('Non Valid Callback in ' . $e -> getName()); protected function addEventListener(Event $event, $callback) { if(!($this -> events instanceof EventCollection)) $this -> events = new EventCollection(); $event -> setCallback($callback); $this -> events -> addEvent($event); } }
Utilizare
In primul rand pentru ca o clasa sa poata sa foloseasca eventuri aceasta trebuie sa fie un ‘copil’ al clasei EventDispatcher, acest lucru ne va permite sa ascultam dar si sa emitem evenimente, in exemplul de jos myClass este ascultator iar myClass2 este emitatorul. Adaugam un eventListener si facem ca callback functia event din myClass, cand va fi chemata clasa dispatchEvent din myClass2 functia noastra (myClass::event()) va fi si ea apelata.
class myClass extends EventDispatcher { public function __construct() { $c = new myClass2(); $c -> addEventListener(new Event('something'), array(&$this, 'event')); $c -> doSomething(); } public function event($event) { echo 'Event Dispatched'; } } class myClass2 extends EventDispatcher { public function doSomething() { $this -> dispatchEvent(new Event('something')); } } $class = new myClass(); // Event Dispatched
Concluzie
Sper ca acest articol a reusit sa va stimuleze interesele pentru evenimente si procesarea evenimentelor, sunteti liber sa folositi clasele cum doriti. Intrebarile si imbunatatirile sunt bine venite! 🙂