Overview 1. Procedural PHP 2. Refactor to Object-Oriented PHP 3. Extensibility 4. Controllers in Model View Controller 5. EventDispatcher concept 6. Refactor to using an EventDispatcher 7. EventDispatcher caveats
John, Customers are unhappy. Send them a “Welcome!” email after they register on the web site. Tell them we are glad to have them as a customer. That’ll teach ‘em. Do it now. The Boss The Boss
Object-Oriented PHP class Customer { public function __construct(array $data) { $this->name = $data['name']; $this->email = $data['email']; } public function getName() { return $this->name; } public function getEmail() { return $this->email; } }
class Controller { // POST http://demcrookidwigitz.com/person public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail(), $customer->getName()); } } Object-Oriented PHP
John, Advertising wants to know how many new customers we’re getting. Setup some logging. I don’t want their grubby hands on the database. That’ll teach ‘em. Do it now. The Boss The Boss
Disk Logging class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(). ' at '.$customer->getEmail(); $dLog->log($msg); } }
John, Marketing wants to run statistics on orders. Keep them away from the database too. Just add to that other log file we setup for Advertising. That’ll teach ‘em. Do it now. The Boss The Boss
More Disk Logging class Controller { public function newCustomer() { // ... $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(). ' at '.$customer->getEmail(); $dLog->log($msg); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); } }
class Controller { public function newCustomer() { // ... $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(). ' at '.$customer->getEmail(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function newCustomer() { // ... $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(). ' at '.$customer->getEmail(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName().' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...');
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
Extensibility [A] system design principle where the implementation takes into consideration future growth. Extensibility - Wikipedia http://en.wikipedia.org/wiki/Extensibility
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } } NOT EXTENSIBLE!
Event Dispatcher - Register Listeners use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $listener = new CustomerListener(); $dispatcher->addListener('customer.register', array($listener, 'onRegister')); // Register more listeners class CustomerListener { public function onRegister(CustomerEvent $event) { // Do some work } } Any PHP Callable true === is_callable()
Event Dispatcher - Register Listeners use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addListener('customer.register', array('CustomerListener', 'onRegister')); // Register more listeners class CustomerListener { public static function onRegister(CustomerEvent $event) { // Do some work } }
Event Dispatcher - Register Listeners use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // Do some work });
Event Dispatcher - Handle the Event use Symfony\Component\EventDispatcher\Event; class CustomerEvent extends Event { protected $customer; public function __construct(Customer $customer) { $this->customer = $customer; } public function getCustomer() { return $this->customer; } }
class Controller { public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } } START
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.new', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.cancel', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } } FINISH
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]');
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $email = new WelcomeEmail(); $email->send($customer->getEmail()); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]');
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]');
use Symfony\Component\EventDispatcher\Event; class CustomerEvent extends Event { protected $customer; public function __construct(Customer $customer) { $this->customer = $customer; } public function getCustomer() { return $this->customer; } }
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); // Wire listeners $listener = new CustomerEmailListener(new WelcomeEmail()); $dispatcher->addListener('customer.register', array($listener, 'onRegister')); class WelcomeEmail { public function send($to, $name) { return mail($to, $this->getSubject(), $this->getMessage($name), $this->getHeaders()); } protected function getSubject() { return 'New Account'; } protected function getMessage($name) { return "Welcome " . $name . "! Your new space has been created! Use this link to login: https://activate.demcrookidwigitz.com/code/Sq9284tWBnWgpjw Thanks! DemCrookidWigitz"; } protected function getHeaders() { $headers = array(); $headers[] = 'From: [email protected]';
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]');
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]');
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $dLog = new DiskLogger('/logs/prod.log'); $msg = 'Sent welcome email to '.$customer->getName(); $dLog->log($msg); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' has registered!'); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } } class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); $twitter->tweet($customer->getName() . ' just ordered from us!'); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } } class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $twitter = new Twitter('demcrookidwigitz', 'b3@tb0Xpr0$'); // Wire listeners $listener = new TwitterListener($twitter); $dispatcher->addListener('order.new', array($listener, 'tweetAtOrderer')); class TwitterListener { public function __construct(Twitter $twitter) { $this->twitter = $twitter; } public function tweetAtOrderer(CustomerEvent $event) { $customer = $event->getOrder(); $msg = $customer->getTwitterHandle().' Thanks for ordering from us!'; $this->twitter->tweet($msg); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $eLog = new EmailLogger('[email protected]'); $eLog->log($customer->getName() . ' cancelled their order...'); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Created order ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $dLog = new DiskLogger('/logs/prod.log'); $dLog->log('Cancelled order number ' . $number); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } } class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.new', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.cancel', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } }
use Symfony\Component\EventDispatcher\Event; class OrderEvent extends Event { protected $order; public function __construct(Order $order) { $this->order = $order; } public function getOrder() { return $this->order; } }
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $diskLogger = new DiskLogger('/logs/prod.log'); // Wire listeners $listener = new OrderLoggerListener($diskLogger); $dispatcher->addListener('order.new', array($listener, 'onNewOrder')); class OrderLoggerListener { public function __construct(DiskLogger $logger) { $this->logger = $logger; } public function onNewOrder(OrderEvent $event) { $order = $event->getOrder(); $this->logger->log('Created order number ' . $order->getNumber()); } }
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $diskLogger = new DiskLogger('/logs/prod.log'); // Wire listeners $listener = new OrderLoggerListener($diskLogger); $dispatcher->addListener('order.new', array($listener, 'onNewOrder')); $dispatcher->addListener('order.cancel', array($listener, 'onCancelOrder')); class OrderLoggerListener { public function __construct(DiskLogger $logger) { $this->logger = $logger; } public function onNewOrder(OrderEvent $event) { $order = $event->getOrder(); $this->logger->log('Created order number ' . $order->getNumber()); } public function onCancelOrder(OrderEvent $event) { $order = $event->getOrder(); $this->logger->log('Cancelled order number ' . $order->getNumber()); } }
class Controller { public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function newCustomer() { $customer = new Customer($_POST); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.register', $event); } public function createOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.new', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.new', $event); } public function cancelOrder() { // ... $event = new OrderEvent($order); $this->dispatcher->dispatch('order.cancel', $event); $event = new CustomerEvent($customer); $this->dispatcher->dispatch('customer.order.cancel', $event); } } FINISH
Caveat - Priority use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // First }); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // Second }); $customer = new Customer(); $customer->setEmail('[email protected]'); $event = new CustomerEvent($customer); $dispatcher->dispatch('customer.register', $event); First Second
Caveat - Priority use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // Second }, 100); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // First }, 200); $customer = new Customer(); $customer->setEmail('[email protected]'); $event = new CustomerEvent($customer); $dispatcher->dispatch('customer.register', $event); First Second
Caveat - Priority use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // Third }, 100); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // First }, 200); $dispatcher->addListener('customer.register', function(CustomerEvent $event) { // Second }, 200); $customer = new Customer(); $customer->setEmail('[email protected]'); $event = new CustomerEvent($customer); $dispatcher->dispatch('customer.register', $event); First Third Second
Adobe Desktop Application Codebase Source: http://stlab.adobe.com/wiki/index.php/File:2008_07_25_google.pdf Event Handling logic All other logic 33% Event Handling bugs All other bugs 50%
Ideas for Utilizing Events • Logging • Offloading expensive operations to a message queue • Email, PDF generation, file system access • Setting “created_at” or “updated_at” on an entity • Updating a search index when persisting an entity • Allowing users of your plug-ins to extend their functionality without modifying your code • What ideas have you come up with?
Further Reading • Introduction to Symfony2 EventDispatcher http://bit.ly/sf2-event-dispatcher • An Introduction to Zend Framework 2 Event Manager http://bit.ly/zf2-event-manater • The S.O.L.I.D. Principles of OO and Agile Design http://bit.ly/uncle-bob-oo-insights