Event driven development in PHP applications are becoming more prevalent. This presentation goes over the origins of the concept from the Observer pattern, details the benefits and drawbacks, and discusses real world application of the pattern.
3. What?to?expect
What are cross-cutting concerns?
Origins from Observer pattern
Asynchronous vs Synchronous
Logic abstraction
Demo
Events in the wild
Advantages and drawbacks
Futher considerations
8. Single?Responsibility?Principle
If a class and its services should be responsible for
one thing, how do we deal with unrelated business
rules that must be addressed by that class?
10. Observer?Pattern
The root of Event Driven Applications began with the observer
pattern which tracks the state of a subject by attaching observers to
the subject so that when it changes, all observers are notified.
11. SplObserver
The interface is a standard lib to implement this
pattern.
SplObserver
An SplSubject object attaches the observer.
The SplSubject then calls an update on the observer when notifying
the registered observers.
13. App?event?in?javascript
Syncronous in order of execution
Asyncronous in order of completion
$('p')
.on('click', function() {
(function() {
console.log('first?');
}());
})
.on('click', function() {
(function() {
console.log('second?');
}());
});
16. Separation?of?Concerns
Use synchronous events to separate chunks of business logic away
from core functionality
Provides for modularity
Allow for unit testing listeners
Multiple messages - multiple listeners
17. Example?Before
<?php
function login($username, $password) {
try {
// get user from db
$user = Repository::get($username, $password);
// Check if an admin
if ($user->role->admin) {
$_SESSION['admin'] = true;
}
// Log user's login
$user->updateLastLogin(time());
Repository::saveUser($user);
} catch (Exception $e) {
return false;
}
return true;
}
18. Example?After
<?php
function login($username, $password) {
try {
// get user from db
$user = Repository::get($username, $password);
// Fire post login event
$event::trigger('afterLogin', compact('user'));
} catch (Exception $e) {
return false;
}
return true;
<?php
$event::listen('afterLogin', function($event) {
if ($event->data['user']->role->admin) {
$_SESSION['admin'] = true
}
});
$event::listen('afterLogin', function($event) {
$event->data['user']->updateLastLogin(time());
Repository::saveUser($event->data['user']);
});
21. CakePHP
Controllers have beforeFilter, beforeRender, and components with
similar callbacks
Models have behaviors with before find/save
Exposed event library
22. Symfony?2
can be used as a standalone event library.
Can be easily incorporated via Composer
EventDispatcher
23. Zend
can be used to create events and listeners of said
events
Can be extracted from Zend, but not as easily as Symfony 2.
EventManagers
26. Decouple?Code
Advantage:
Modular design can reduce core functionality bugs when modifying
modules.
Allows for open frameworks to allow third parties to implement
custom solutions without modifying core files.
Disadvantage:
Code is harder to follow and needs good organizational
management.
Documentation of what events will be called when is almost a
must.
27. Plugin?Architecture
Advantage:
Enable or disable plugins on the fly.
Essential for open source targeting developers to implement.
Disadvantage:
No dependencies should exist be between plugins.
28. Testing
Advantage:
Test the listeners separate from the core functionality.
Execute listeners from core test cases via external event triggers.
Mock event callbacks to test event trigger placement.
Disadvantage:
Multiple event bindings in test suites results in undesired event
triggers.
Unbinding specific event callbacks can be difficult to do.