Symfony Events

4,289 views
4,155 views

Published on

An introduction to symfony events. Includes:

- Symfony Events Overview
- Conceptual Examples
- Utilizing Symfony Core Events
- Creating Your Own Event System

Published in: Technology, Business
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,289
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
63
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Symfony Events

  1. 1. Symfony Events Every event happens for a reason Brent Shaffer @bshaffer CentreSource Interactive Agency www.brentertainment.com June 1st, 2010
  2. 2. Symfony Events “All [symfony] events are blessings given to us to learn from.” - Elizabeth Kubler-Ross “Great [symfony] events make me quiet and calm; it is only [fat controllers] that irritate my nerves.” - Queen Elizabeth “Keep [symfony events] around for when shit gets crazy. Cause shit will get crazy!” - Carp Guy
  3. 3. What are Symfony Events Overview • Symfony events are part of the Event Dispatcher component • Implements the Observer design pattern (Design Patterns, GoF) • “...The subject maintains a list of its dependants, called observers, and notifies them automatically of any state changes” • Lightweight, consists of only 2 classes 1. sfEventDispatcher - object responsible for maintaining a register of listeners and calling them whenever an event is notified 2. sfEvent - object that stores information about the notified event
  4. 4. sfEventDispatcher Connect - Connects a listener to a given event name. $dispatcher->connect('event.name', array($php, 'callable')); Notify - Notifies all listeners of a given event. $dispatcher->notify(sfEvent $event); Notify Until - Notifies all listeners of a given event until one returns a non null value. $dispatcher->notifyUntil(sfEvent $event); Filter - Filters a value by calling all listeners of a given event. $dispatcher->filter(sfEvent $event, $value);
  5. 5. sfEventDispatcher Where is it? sfContext and sfApplicationConfiguration hold a single sfEventDispatcher instance and facilitate it to other classes How do I access it? // sfContext and sfApplicationConfiguration: $this->context->getEventDispatcher(); sfApplicationConfiguration::getActive()->getEventDispatcher(); // sfFormSymfony subclasses self::getEventDispatcher(); // sfActions subclass / sfBaseTask subclass / sfPHPView: $this->dispatcher
  6. 6. sfEvent Constructor public function __construct($subject, $name, $parameters = array()) Subject The subject of the event (the object notifying the event, or object the event is about. It can also be null); Name The event name Parameters An array of parameters to pass to the listeners (an empty array by default) The event object can also be accessed as an array to get its parameters $method = $event['method']; // Is the same as $parameters = $event->getParameters(); $method = $parameters['method'];
  7. 7. Conceptual Example Receptionist with Four Employees Notify A client calls in for Employee One to call them back Receptionist (event dispatcher) // aClient.class.php $this->dispatcher ->connect('employee_one.becomes_available', 1 4 array($this, 'callMe')); A lawyer calls in, needs Employee One to sign 2 3 some lawyer stuff // aLawyer.class.php $this->dispatcher ->connect('employee_one.becomes_available', array($this, 'signMyStuff')); Employee One lets secretary know when he’s available. // EmployeeOne.class.php public function becomesAvailable() { $this->dispatcher->notify(new sfEvent($this, 'employee_one.available')); }
  8. 8. Conceptual Example Receptionist with Four Employees Notify Employee Three wants to know when employee 2 Receptionist (event dispatcher) leaves, so he can eat his leftovers // EmployeeThree.class.php $this->dispatcher->connect('employee_two.goes_home', 1 4 array($this, 'stealLeftovers')); 2 3 public function stealLeftovers(sfEvent $event) { $employeeTwo = $event->getSubject(); $this->eat($employeeTwo->getLeftovers()); } Employee Two lets secretary know when he’s leaving. // EmployeeTwo.class.php public function goesHome() { $this->dispatcher->notify(new sfEvent($this, 'employee_two.goes_home')); }
  9. 9. Conceptual Example Receptionist with Four Employees Notify Until Employee 4 puts out an add in the newspaper Receptionist (event dispatcher) Now Hiring: Personal assistant. Strong communication skills. Willing to take excessive sexual 1 4 harassment. Call before 5:00 PM 2 3 Individuals call in to register // aProspect.class.php $this->dispatcher->connect('employee_four.job_offering', array($this, 'callMe')); // aFeministMovement.class.php $this->dispatcher->connect('employee_four.job_offering', array($this, 'sue')); Employee Four notifies the registered listeners until he finds an employee // EmployeeFour.class.php (at 5:00) $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'employee_four.job_offering')); if($event->isProcessed()) $employee = $event->getReturnValue();
  10. 10. Conceptual Example Receptionist with Four Employees Filter Employee 4 puts out an add in the newspaper, Receptionist yadda yadda, but this time, he wants a list. (event dispatcher) // aProspect.class.php $this->dispatcher 1 4 ->connect('employee_four.job_offering', array($this, 'addToList')); 2 3 public function addToList($event, $list) { $list[] = $self; $event->setReturnValue($list); } Employee Four notifies the registered listener and provides the item to filter // EmployeeFour.class.php (at 5:00) $event = $this->dispatcher->filter(new sfEvent($this, 'employee_four.job_offering'), $list); $list = $event->getReturnValue();
  11. 11. Utilizing Symfony Core Events Lazy-add mobile templates We will now demonstrate how useful symfony core events can be in your application We will show how to add mobile-specific layouts to your existing application. “Lazy-add” - add mobile templates as you go while keeping everything without a mobile template still accessible. In other words, if a mobile template exists, render it for mobile devices. Otherwise, render the default template. Based largely on the blog post “How to create an optimized version of your website for the iPhone in symfony 1.1”
  12. 12. Utilizing Symfony Core Events Lazy-add mobile templates Connect to “filter parameters” event, add request format for the appropriate user agent // ProjectConfiguration.class.php public function setup() { ... $this->dispatcher->connect('request.filter_parameters', array($this, 'filterRequestParameters')); } public function filterRequestParameters(sfEvent $event, $parameters) { $request = $event->getSubject(); if (preg_match('#Mobile/.+Safari#i', $request->getHttpHeader('User-Agent'))) { $request->setRequestFormat('m'); } return $parameters; }
  13. 13. Utilizing Symfony Core Events Lazy-add mobile templates Connect to “view.configure_format” event to only set if the template exists // ProjectConfiguration.class.php public function setup() { ... $this->dispatcher->connect('view.configure_format', array($this, 'configureMobileFormat')); } public function configureMobileFormat(sfEvent $event) { if ('m' == $event['format']) { $view = $event->getSubject(); $dir = sfConfig::get('sf_app_module_dir').'/'.$view->getModuleName().'/templates/'. $view->getActionName().$view->getViewName().$view->getExtension(); if (!file_exists($dir)) { $view->setExtension('.php'); } } }
  14. 14. Utilizing Symfony Core Events Lazy-add mobile templates Set our mobile format in factories.yml // factories.yml all: request: class: sfWebRequest param: formats: m: text/html ... Now, we can add mobile templates as we go, while keeping the rest of the site as-is!
  15. 15. Creating Your Own Events Alert System We will now demonstrate how creating your own set of events can be useful. Using events keeps your libraries modular and decoupled. It also makes them very easy to unit test. You want to build a system in your application that sends email alerts out for various triggers. You’re smart, so you will accomplish this using the event dispatcher // ProjectConfiguration.class.php public function setup() { ... include_once sfConfig::get('sf_lib_dir').'/alert/sfAlertDispatcher.class.php'; $this->alertDispatcher = new sfAlertDispatcher(); $this->alertDispatcher->connectEvents($this->dispatcher); }
  16. 16. Creating Your Own Events Alert System Handle your events inside your model. Keep things modular. // lib/alert/sfAlertDispatcher.class.php class cfitAlertDispatcher { public function connectEvents(sfEventDispatcher $dispatcher) { // = Raise Alerts = $dispatcher->connect('contact.form_submitted', array($this, 'alertContactForm')); $dispatcher->connect('support.ticket_submitted', array($this, 'alertTicketSubmitted')); // = Resolve Alerts = $dispatcher->connect('support.ticket_closed', array($this, 'resolveSupportTicket')); } }
  17. 17. Creating Your Own Events Alert System Write your implementation logic for the appropriate listeners // lib/alert/sfAlertDispatcher.class.php class cfitAlertDispatcher { ... public function alertContactForm(sfEvent $event) { // ...do alert logic, etc $form = $event->getSubject(); $this->mailer->send($this->getContactEmailFromForm($form)); } public function alertTicketSubmitted(sfEvent $event) { // Notice how easy this logic will be to unit test! $ticket = $event->getSubject(); if($ticket->isAtleastCritical()) { $this->mailer->send($this->getEmailFromTicket($ticket)); } } ... }
  18. 18. Creating Your Own Events Alert System Add the logic in your application for triggering the events // contactActions.class.php ... $this->dispatcher->notify(new sfEvent($form, 'contact.form_submitted')); // ticketActions.class.php ... $dispatcher->notify(new sfEvent($ticket, 'support.ticket_submitted')); ... // Ticket.class.php public function close(sfEventDispatcher $dispatcher) { ... $dispatcher->notify(new sfEvent($this, 'support.ticket_closed')); }
  19. 19. Creating Your Own Events Alert System And that’s it! The rest is a matter of implementation logic for your specific application Notice how easy cfitAlertDispatcher is to unit test. Get rid of all those fat controllers! And one last quote... “...Gather in your resources, rally all your faculties, marshal all your energies, focus all your capacities upon mastery of [symfony events]” - John Haggai
  20. 20. Questions? Brent Shaffer @bshaffer CentreSource Interactive Agency www.brentertainment.com 2010-05-01

×