Skip to content
Newer
Older
100644 335 lines (232 sloc) 9.03 KB
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
1 # Propel-Listener-Behavior
2
3 The Propel Listener Behavior let's you add listeners to propel generated objects. Thus it is
4 possible that these listeners are notified when a specific event on a propel generated object
5 occurs. The listeners design is inspired by the observer pattern and the W3C EventTarget
6 Interface.
7
8 E.g. if your model consists of an Event object an your app is connected to a google calender
9 you wish those two events stay in sync. So you register a listener at your Event object and
10 whenever something gets changed there, the listener gets notified and can change the event
11 at the google calender accordingly.
12
13 ## Installation
14
15 ### Generator
b3d1c8a @gossi fix links in the readme
authored Jul 23, 2011
16 At first you need the [src/generator](propel-listener-behavior/tree/master/src/generator) folder from github. In your `build.properties` you need
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
17 to add `propel.behavior.listener.class` and point it to the `src/generator/ListenerBehavior`
18 file, using the dot-notation.
19
20 ### Runtime
21 The Propel Listener Behavior comes with it's own runtime to make it work correctly and with
22 all its features.
b3d1c8a @gossi fix links in the readme
authored Jul 23, 2011
23 Include the [src/runtime/ListenerBehavior.php](propel-listener-behavior/tree/master/src/runtime/ListenerBehavior.php) file in your
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
24 source code.
25
26 ## Usage
27
28 ### Schema
29 The behavior can be added to either the database or a specific table.
30
31 Database:
32
33 <database name="...">
34 <behavior name="listener"/>
35 <table>
36 ...
37 </table>
38 </database>
39
40 Table:
41
42 <database name="...">
43 <table>
44 <column .../>
45 <behavior name="listener"/>
46 ...
47 </table>
48 </database>
49
50 However, this will create a new table (and thus a new object) in your model to store your
21d128b @gossi - Added phpName Parameter
authored Jul 29, 2011
51 listeners. By default this table is `listener`. You can change this using parameters.
52
53 *Note: Obviously this behavior can be added to tables, there is not much sense in it. This
54 behavior is best placed as a database behavior.*
55
56 #### Parameters
57 Parameters to modify the behavior.
58
59 ##### Table Parameter
60 With the `table` you can name the listener table in your schema. By default this is
61 `listener`. By passing the `table` parameter to the behavior, to prevent interfering usage
62 with your model, like this:
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
63
64 <behavior name="listener">
21d128b @gossi - Added phpName Parameter
authored Jul 29, 2011
65 <parameter name="table" value="my_listener_table"/>
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
66 </behavior>
67
21d128b @gossi - Added phpName Parameter
authored Jul 29, 2011
68 ##### phpName Parameter
69 If you don't want the generated propel object named after your table parameter you can change
70 modify this with the `phpName` parameter:
71
72 <behavior name="listener">
73 <parameter name="table" value="my_listener_table"/>
885144e @gossi Fixed some errors in the readme
authored Sep 18, 2011
74 <parameter name="phpName" value="Listener"/>
21d128b @gossi - Added phpName Parameter
authored Jul 29, 2011
75 </behavior>
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
76
21d128b @gossi - Added phpName Parameter
authored Jul 29, 2011
77 This will create a table named `my_listener_table` and a propel object `Listener`.
78
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
79 ### Listener Events
80
81 You can add listeners very differently, according to your needs, offering more and more
82 features the more advanced it gets. Listeners can be attached and listen to differend events,
83 these are:
84
85 * preInsert
86 * postInsert
87 * preUpdate
88 * postUpdate
89 * preSave
90 * postSave
91 * preDelete
92 * postDelete
93
94 ### Global and Local Listeners
95
96 Listeners can be added in two forms. As **global**, then they were added (statically) on a
97 record like `Table::addGlobalListener(...)`. Global listeners react on each object
98 instantiated from the attached class.
99
100 **Local** listeners instead are attached to specific objects. E.g.
101
102 $t = new Table();
103 $t->addListener(...);
104
105 These listeners will only react, when an event on this specific object occurs.
106
107 ### Attaching Listeners
108
109 For the demos below, let's assume our object where we can attach
110 listeners is named `Table`. In the demos, local listeners are used but global listeners
111 working exactly the same using the static `addGlobalListener` and `removeGlobalListener`
112 methods.
113
114 #### Simplest Method: Simple Function
115
116 function myListenerFunction($e) {
117 // ... do something here
118 }
119
120 $t = new Table();
121 $t->addListener('myListenerFunction');
122
123 The simplest one is a function that is passed as a string. This function will react on each
124 of the above mentioned events.
125
126 #### Function that reacts on a specific Event
127
128 function myListenerFunction($e) {
129 // ... do something here
130 }
131
132 $t = new Table();
133 $t->addListener(array(
134 'callback' => 'myListenerFunction',
135 'event' => 'postSave'
136 ));
137
138 Now we extended the functionality by adding the event, at which the listener should be
139 notified.
140
141 #### Passing Parameters through Listeners
142
143 function myListenerFunction($e) {
144 // ... do something here
885144e @gossi Fixed some errors in the readme
authored Sep 18, 2011
145 echo $e['params']['my_super_important_id']; // 42
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
146 }
147
148 $t = new Table();
149 $t->addListener(array(
150 'callback' => 'myListenerFunction',
151 'event' => 'postSave',
152 'params' => array(
153 'my_super_important_id' => 42
154 )
155 ));
156
157 This way you can pass information to your listener, using the params attribute of your
158 configuration array. The params will later be accessible from your listener.
159
160 #### Using Classes as Listeners
161
162 In an object oriented application functions are seen very rare. Thus it is possible to get
163 classes notified about occuring events (This example is the same as the simplest method above
164 but for classes).
165
166 class MyListener {
167 public function handleEvent($e) {
168 // ... do something here
169 }
170 }
171
172 $t = new Table();
173 $t->addListener('MyListener');
174
175 *Note: Internally when the event occurs a new object of MyListener is instantiated, as:*
176
177 $obj = new MyListener();
178 $obj->handleEvent($e);
179
180 *Note 2: If no callback is given or callback is no method on the class, `handleEvent` is
181 called (see next section, too)*
182
183 #### Using Classes with more Sugar
184
185 If you have a proper method on your class, you can use that for sure.
186
187 class MyListener {
188 public function tableGotUpdated($e) {
189 // ... do something here
190 }
191 }
192
193 $t = new Table();
194 $t->addListener(array(
195 'on' => 'MyListener',
196 'callback' => 'tableGotUpdated',
197 'event' => 'postUpdate'
198 ));
199
200 #### Using the ListenerInfo Interface
201
202 If you already have an internal dispatcher for your app and you want to use that, the
203 `ListenerInfo` interface is the right one for you.
204
205 class MyListenerInfo implements ListenerInfo {
206 // ... other stuff here
207
208 public function getListenerInfo() {
209 return array(
210 'on' => 'MyCoolClassThatReactsOnListenerEvents',
211 'callback' => 'sooperDooperHaandler'
212 );
213 }
214
215 // ... another stuff there
216 }
217
218 $t = new Table();
219 $t->addListener(new MyListenerInfo());
220
221 #### Using the bundled RecordListener
222
223 The bundled RecordListener ships with the propel listener behavior and is part of its runtime.
224 With the RecordListener you can attach Listeners on an object that passes the reaction to
225 other propel objects. Sounds complicated? Example code:
226
227 $t = new Table();
228 $t->setName('Unchanged Record');
229 $t->save();
230
231 $o = new OtherTable();
232 $o->setOther($t->getId());
233 $o->save();
234
235 $t->addListener(new RecordListener(array(
236 'event' => 'postUpdate',
237 'target' => 'OtherTable',
238 'find' => 'findOneByOther',
239 'param' => $t->getId()
240 )));
241
242 Explanation: We have two propel objects $t from `Table` and $o from `OtherTable`. A listener
243 is added on `Table` that reacts on the *postUpdate* event. The target, find and param
244 parameters that are passed to the RecordListener are placed that way:
245
246 function postUpdateEventOnTableHappened($e) {
247 $target = {target}Query::create();
248 $result = $target->{find}({param});
249 }
250
251 and results in that code:
252
253 function postUpdateEventOnTableHappened($e) {
254 $target = OtherTableQuery::create();
255 $result = $target->findByOther($t->getId());
256 }
257
258 this will get evaluated. Thus `$result` contains our `OtherTable` object `$o` from above and
259 `handleEvent` will be invoked.
260
261 #### Removing listeners
262
263 Removing listeners is been done by either the static `removeGlobalListener` or the
264 `removeListener` method. It is absolutely necessary to pass the same arguments for the removal
265 as you passed for the adding. This is how listeners get identified internally.
266
267 ## References
268
269 Full references.
270
271 ### addListener/getListenerInfo Parameters
272
273 `addListener` takes an array as argument, where `getListenerInfo` should return an array.
274 Both use the same keys. They are:
275
276 #### (string) callback
277
278 Function or method name.
279
280 #### (string) on
281
282 A class name.
283
284 #### (string) event
285
286 The event on which the listener should occur. See the list from "Listener Events" above.
287
288 #### (array) params
289
290 An array for user-defined params.
291
292 ### Event
293
294 When an event occurs, the callback function/method is invoked and array is passed with
295 more information about the event.
296
297 #### (string) event
298
299 The event which occured.
300
301 #### (object) target
302
303 Propel-object on which the event occured.
304
885144e @gossi Fixed some errors in the readme
authored Sep 18, 2011
305 #### (array) params (optional)
306
307 User defined parameters.
308
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
309 ### RecordListener
310
311 The `RecordListener` takes the parameters as an array in the constructor. They are:
312
313 #### (string) target
314
315 Which propel object should the event passed on.
316
317 #### (string) find
318
319 The find method, that will be invoked on the target-query object.
320
321 #### (string) param
322
323 The search param for the find method.
324
325 #### (string) method
326
327 The method that will be invoked on the target object. To find the right method in the target
328 object, the listener-behavior tries the following steps:
329
330 1. method is passed as param
885144e @gossi Fixed some errors in the readme
authored Sep 18, 2011
331 2. `onEvent`, means: if `postUpdate` is invoked, the method `onPostUpdate` will be tried to
6245f0f @gossi - propel-behavior-listener updated
authored Jul 23, 2011
332 call.
333 3. If none of the above methods is found in the target object, `handleEvent` is called.
334
335
Something went wrong with that request. Please try again.