Я хотел бы реализовать систему событий в моей пользовательской структуре MVC, чтобы позволить развязать классы, которые должны взаимодействовать друг с другом. В принципе, способность любого класса инициировать событие и любой другой класс, который слушает, чтобы это событие могло подключиться к нему.
Тем не менее, я не могу найти правильную реализацию, учитывая, что природа php не имеет ничего общего с архитектурой.
Например, предположим, что у меня есть модель User, которая каждый раз, когда она обновляется, запускает событие userUpdate. Теперь это событие полезно для класса A (например), так как оно требует применения собственной логики при обновлении пользователя. Однако класс A не загружается, когда пользователь обновляется, поэтому он не может связываться с событиями, вызванными объектом User.
Как вы можете обойти такой сценарий? Я подхожу к нему неправильно?
Благодарим за любую идею
Перед вызовом события должен быть экземпляр класса A, потому что вы должны зарегистрироваться для этого события. Исключение было бы, если бы вы зарегистрировали статический метод.
Допустим, у вас есть класс User, который должен инициировать событие. Сначала вам нужен (абстрактный) класс диспетчера событий. Такая система событий работает как ActionScript3:
abstract class Dispatcher { protected $_listeners = array(); public function addEventListener($type, callable $listener) { // fill $_listeners array $this->_listeners[$type][] = $listener; } public function dispatchEvent(Event $event) { // call all listeners and send the event to the callable's if ($this->hasEventListener($event->getType())) { $listeners = $this->_listeners[$event->getType()]; foreach ($listeners as $callable) { call_user_func($callable, $event); } } } public function hasEventListener($type) { return (isset($this->_listeners[$type])); } }
Теперь ваш пользовательский класс может расширить этот Диспетчер:
class User extends Dispatcher { function update() { // do your update logic // trigger the event $this->dispatchEvent(new Event('User_update')); } }
И как зарегистрироваться на это мероприятие? Скажем, у вас есть класс A с update
метода.
// non static method $classA = new A(); $user = new User(); $user->addEventListener('User_update', array($classA, 'update')); // the method update is static $user = new User(); $user->addEventListener('User_update', array('A', 'update'));
Если у вас есть правильная автозагрузка, можно вызвать статический метод. В обоих случаях Event
будет отправлено как параметр для метода update
. Если вам нравится, вы также можете иметь абстрактный класс Event.
Я сделал очень простой диспетчер событий PHP / Event Hander для себя, он доступен для тестирования и был использован на моих сайтах.
Если вам это нужно, вы можете взглянуть.