This is going to be hopefully the first part of PHP pattern series. Unfortunately a lot of programming pattern examples are usually explained in an obscured fashion and most of the time in some other programming language. Though this has improved much in the recent time, I still feel I should try my hand at explaining thims in a simple fashion.
We will start with one of the most useful patterns that is present pretty much everywhere (ironically I try to avoid it like fire in PHPixie, but I’ll explain later why), the Observer. If you have any experience with event driven programming, even using filters in WordPress, you probably will recognize and understand it almost instantly. And yes, I will use fairies as examples.
The Problem
In our forest each glade will be looked after by numeroues fairies that will do their best to keep it safe and beautiful. A lot of things may happen here, like a strong rain might fall, or hawks may come looking for pray. A class for these events may look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Event{
//Type of the event, like 'rain', 'hawks', etc.
protected $_type;
//Details of the event, like the strength of the rain
//or the amount of hawks spotted
protected $_details;
public function __construct($glade, $type, $details = array()){
$this->_type = $type;
$this->_details = $details;
}
public function type() {
return $this->_type;
}
public function details() {
return $this->_details;
}
}
Additionally there are many kinds of fairies, and each can contribute in a different way. They are always observing the glade, looking for an opportunity to help and reacting to the events that occur.
1
2
3
4
5
6
7
8
9
10
11
12
<?php
abstract class Fairy{
protected $_name;
public function name(){
return $this->_name;
}
public abstract function react($event, $glade);
}
Before we dive into some mythology we also have to make a class for the glade itself. Being also magical it will know about which fairies can help her with any particular event type and promptly notify them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Glade{
//An associative array, where key being the type of an event
//and the value holding an array of fairies that would help
protected $_fairies = array();
//Make a fairy responsible for a particular event
public make_responsible ($fairy, $event_type) {
if(!isset($this->_fairies[$event_type]))
$this->_fairies[$event_type] = array();
$this->_fairies[$event_type][] = $fairy;
}
public something_happened($event) {
if(!isset($this->_fairies[$event->type()]))
return;
foreach($this->_fairies[$event->type()] as $fairy)
$fairy->react($event, $glade);
}
}
Now let’s look into two kinds of fairies that will inhabit the glade:
Sprites – friendly fairies that will helps flowers bloom in spring, and take care of them in autumn “`php?start_inline=1 class Sylph extends Fairy {
public function chaseawayhawks($event, $glade) { //…some code here… }
public function blowwindsto_pollinate($event, $glade) { //…some code here… }
public function react($event, $glade) { if($event->type() == ‘hawks’) return $this->chaseawayhawks($event, $glade);
1
2
if($event->type() == 'spring')
return $this->blow_winds_to_pollinate($event, $glade);
}
} ”“``php?start_inline=1 class Sprite extends Fairy {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function help_bloom($event, $glade) {
//...some code here...
}
public function take_care_of_flowers($event, $glade) {
//...some code here...
}
public function react($event, $glade) {
if($event->type() == 'autumn')
return $this->take_care_of_flowers($event, $glade);
if($event->type() == 'spring')
return $this->help_bloom($event, $glade);
}
} ”`
Of course the magical glade will also know that it doesn’t need all fairies to look after all events, so it sometimes will make a fairy do only one particular thing. Since we have everything set up now we can create a glade and add fairies to it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$trixie = new Sylph('Trixie');
$tinkerbell = new Sylph('Tinkerbell');
$rosetta = new Sprite('Rosetta');
$silvermist = new Sprite('Silvermist');
$glade = new Glade();
//Trixie will both help with hawks and work in spring
$glade->make_responsible($trixie, 'hawks');
$glade->make_responsible($trixie, 'spring');
//Tinkerbell will work only on pollinating
$glade->make_responsible($tinkerbell, 'spring');
//Rosetta will help with flowers in spring and autumn
$glade->make_responsible($rosetta, 'spring');
$glade->make_responsible($rosetta, 'autumn');
//Silvermist will work only when spring comes
$glade->make_responsible($silvermist , 'spring');
//Spring is coming...
$spring = new Event('spring');
$glade->something_happened($spring);
And that’s it. Programmatically speaking we subscribed our observers (fairies) to particular events on the subject object (glade). We can pass additional data with each event too. More complex implementations would allow events to be altered while they are processed and also be cancellable. I hope you enjoyed this little tutorial and will look out for more.
Now the reeason why I personally don’t like using observers or events is because they lead to non-linear code. This pattern is best suited for developing user interfaces like writing javascript for your wesite. When you add a click event handler in jQuery you are basically using an observer, though instead of an object you subscribe closures and functions. It makes a lot of sense there, since you don’t know what the user is going to do and the whole application is non-linear.
Now if you are writing backend code in PHP there is really just a single “real user event” – HTTP request, from that point on the flow is predictable so it may be written in a linear fashion. The reason why WordPress received a lot of criticism is because every plugin could apply a filter to change some piece of output or control a point of execution. Debugging such systems is hell since filters can subscribe and unsubscribe on the fly, so at times it’s pretty hard to pinpoint which filter is messsing things up. In modern PHP frameworks events are used to patch up bad design practices, allowing the developer to pass control around different classes, calling all kinds of events. But what if one of your event handlers raises an event of it’s own? Now you are handling nested events and you might as well give up at this point. There is a way around this though: Define handlers explicitly without allowing dynamic subscription to events like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Glade{
protected $_fairies = array();
//We define all our fairy hadlers only during construction
public function __construct($handlers) {
foreach($handlers as $type=>$fairies)
foreach($fairies as $fairy)
$this->make_responsible($fairy, $type);
}
//And make this method not accessible from outside
protected make_responsible($fairy, $event_type){
//...rest of the code
}
//...rest of the code
This restricts us much more, but now we always know what is going to get executed, so we made it better. The second problem is that now we need to pass the glade object everywhere, because we don’t know when something will descide to call an event upon it, lazy developers simplify it by making Glade a singleton, or making a static method that will return a glade, thus introducing global scope to their program. And global scope is hard to test and debug. The bottomline is:
Events should only be external (like user clicks) and not internal (like please filter this piece of text). Don’t introduce global scope or you WILL regret it.
Fun fact: A Sprite is a type of a fairy that is responsible for leaves changing colors with the passing of the seasons. BFor this reason bitmaps in computer graphics are referre to as “sprites”.
P.S. I actually do like the simplicity of WordPress.