My Blog

contains PHP and other web related content. (Sometimes there are some off topic things - don't freak out!)

The Observer Pattern in PHP: Refactored

You may remember the article I wrote about the observer pattern in php – but it lacked some of PHP’s advanced features.

In this next example, I’m not going to explain the logic as much – read the original post for more – but I did comment it pretty thoroughly. Here are the things that I added, however:

  • Type hinting in functions
  • Abstract classes
  • Interfaces
  • A registry of observers

So, here is the code:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
 * twitter transport from "library" - on successful tweet will print it out 
 */
class twitterTransport
{
    public function __construct()
    { /** logic here **/ }
 
    public function tweet(twitterMessage $object)
    { /** logic here **/  print $object->message . ' was just tweeted'; }
}
 
/**
 * url shortener from "library" - just replaces [url] with [u] in a string
 */
class urlShortener
{
    public function shorten($message)
    {
        return str_replace('[url]', '[u]', (string) $message);
    }
}
 
/**
 * twitter message class - very simple - just holds the message inside itself as a string
 */
class twitterMessage
{
    public $message = '';
 
    public function __construct($message)
    {
        $this->message = (string) $message;
    }
}
 
/**
 * Observer for shortening URLs
 *
 * This class gets envoked when there is a PREPOST action, and invokes
 * the urlShortener::shorten() against it
 * @see iObserver
 */
class urlShortenerObserver implements iObserver 
{
    /**
     * Tells the type of observing this will do
     * @return string
     */
    public static function getType()
    {
        return 'PREPOST';
    }
 
    /**
     * The notification method - is called when a PREPOST is done. shortens url
     * @param twitterMessage $object
     */
    public function notify($object)
    {
        $urlShortener = new urlShortener();
        $object->message = $urlShortener->shorten($object->message);
    }
}
 
/**
 * The twitter message sender, is observable, sends a message with the postMessage
 * function
 * @see observable
 */
class twitterTransportObservable extends observable
{
    /**
     * post a message to twitter, notifying any observers
     * @param twitterMessage $object
     * @see twitterTransport
     */
    public function postMessage(twitterMessage $object)
    {
        $this->_notify('PREPOST', $object);
 
        $sender = new twitterTransport();
        $sender->tweet($object);
 
        $this->_notify('POSTED', $sender);
    }
}
 
/**
 * abstract observable class - extended for all observable items, contains the array
 * of observers, the register and the notify commands
 */
abstract class observable
{
    /**
     * @var array the observer classes
     */
    protected $_observers = array();
 
    /**
     * used for registering observers, or adding them to the array
     *
     * Keep in mind, this adds them in the same order as they're added to
     * the array, so that may affect the final outcome
     *
     * @param string $type The type of observer, hook name
     * @param object $observer The observer class
     */
    public function registerObserver($type, iObserver $observer)
    {
        if (empty($type)) throw new exception("type was empty when registering " . get_class($observer));
        if (!isset($this->_observers[$type])) $this->_observers[$type] = array();
        $this->_observers[$type][] = $observer;
    }
 
    /**
     * used to notify self of actions of a certain type, launches observers
     *
     * @param string $type The Type of observer, the hook
     * @param object $object The observer object
     */
    protected function _notify($type, $object)
    {
        if (isset($this->_observers[$type])) {
            foreach ($this->_observers[$type] as $observer) {
                $observer->notify($object);
            }
        }
    }
}
 
/**
 * interface for any observer classes
 */
interface iObserver
{
    public function notify($object);
    public static function getType();
}
 
/**
 * launching code
 */
 
/**
 * global observers is an array of items which are shared in all launching software
 * tells which observers are associated with with observable
 */
$globalObservers = array('twitterTransportObservable'=>array('urlShortenerObserver'));
 
 
$tweeter = new twitterTransportObservable();
 
/**
 * assign all observers from our globalObservers
 */
if (isset($globalObservers['twitterTransportObservable'])) {
    foreach ($globalObservers['twitterTransportObservable'] as $observer) {
        $tweeter->registerObserver(call_user_func(array($observer, 'getType')), new $observer);
    }
}
 
$message = new twitterMessage("this is my message [url]");
 
$tweeter->postMessage($message);

Tags:

One Response to “The Observer Pattern in PHP: Refactored”

Leave a Reply

  • twitter loader

Follow me on twitter: @aaronsaray

The views on this website are my own and do not reflect the opinions of my employer or clients.
Creative Commons License Home | Open Source | Book | Music | Art | Bio | Resume | Contact
My Baby