<ac:macro ac:name="info"><ac:parameter ac:name="title">Zend_Message</ac:parameter></ac:macro> <ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
Zend_Message provides an infrastructure to relay messages between objects that don't necessarily know eachother. Also, this might be of interest for the Zend_Tool CLI tooling? An implementation of this proposal is available in Zym.
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
Zend Framework: Zend_Message Component Proposal
Proposed Component Name
Zend_Message
Developer Notes
http://framework.zend.com/wiki/display/ZFDEV/Zend_Message
Proposers
Matthew Weier O'Phinney
Alexander Veremyev (Zend Liaison)
Revision
1.5 - 16 June 2008: Renamed, added usecase from comments
1.4 - 11 March 2008: updated class skeletons and text
1.3 - 20 Februari 2008: Updated link and added another usecase
1.2 - 3 January 2008: Added some use cases, operation description and updated skeletons
1.1 - 30 December 2007: Refactoring and renaming
1.0 - 29 December 2007: Setting up first draft (wiki revision: 32)Table of Contents
1. Overview
This provides a loose coupling between components and makes your app more flexible.
2. References
3. Component Requirements, Constraints, and Acceptance Criteria
- This component must provide a clean, non-intrusive way to handle event notification
- Must not require existing classes to implement interfaces or extend classes for it to work
4. Dependencies on Other Framework Components
- Zend_Exception
5. Theory of Operation
The operation is very simple, but also very powerful. You can attach an object to an event by calling the notification center's attach() method.
This method takes the observer and the name of the event as argument. More than one object can register to the same event.
When a message is sent, all objects that subscribed to that event will be notified in order of subscription.
By default the observer's notify() method will be called. You can also register another method when registering the observering object at the message dispatcher.
The message constructor takes three arguments (of which the last is optional). The first is the name of the message. The second is (usually) the object that sent the message.
The last argument is an array that allows for extra data to be sent along with the message.
When attaching an observer to an event you can either use a string to attach it to just one event, or provide an array with multiple event names. (See usecase UC-02)
When you attach an observer to an event with an asterisk in the name, the asterisk will be used as wildcard. See usecase UC-03 for an example.
6. Milestones / Tasks
- Milestone 1: [DONE] finish this proposal
- Milestone 2: [DONE] write documentation
- Milestone 3: [DONE] write unit tests
- Milestone 4: [IN PROGRESS] process comments
- Milestone 5: get approval and move the component to incubator
- Milestone 6: finish component and move it to core
7. Class Index
- Zend_Message
- Zend_Message_Dispatcher
- Zend_Message_Registration
- Zend_Message_Exception
31 Comments
comments.show.hideDec 29, 2007
fc
<p>Hi Jurren, I really like your proposal, it's a simple and powerful solution to system notifications.</p>
<p>Some feedback</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
Zend_Notification_Center {
// public function postNotification($name, $object, array $userInfo = array())
public function postNotification($message, $object, array $info = array())
}
Zend_Notification {
// public function getName()
public function getMessage()
// public function getUserInfo()
public function getInfo()
}
]]></ac:plain-text-body></ac:macro>
<p>IMO, it would be more appropriate changing $name for $message and $userInfo for $info. That way you can get the message using $notification->getMessage() - instead of $notification->getName().</p>
<p>Also, Zend_Notification can refer to anything. System notification, event notification, reminders, etc. So I think this is a great opportunity to introduce a Zend_System component:</p>
<p>Zend_System_Notification</p>
<p>Well done <ac:emoticon ac:name="smile" /></p>
Dec 29, 2007
fc
<p>Also, I just realised that the word "post" in the postNotification() method might lead to confusion, so to avoid confusion and keep it consistent with other classes you can call it addNotification().</p>
Dec 29, 2007
Jurrien Stutterheim
<p>I like your naming suggestions, although I'm not sure about addNotification(). addNotification would suggest the notification gets added to some sort of queue, while instead it gets broadcasted immediately.</p>
Dec 29, 2007
fc
<p>Yes, my mistake sorry, I was thinking about queues when I wrote that. Because in the future I might want to inject this component into a debugger to see what messages are being passed to other objects. But forget about it, I'll think about this later on. </p>
<p>So, going back to the postNotification() method, what about:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
// Zend_Notification_Center::postNotification()
Zend_Notification_Center::notify()
// Zend_Notification_Observer_Interface::notify()
Zend_Notification_Observer_Interface::getNotification()
]]></ac:plain-text-body></ac:macro>
<p>So, you notify the object and then the object gets notified.</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$this->_notificationCenter->notify(this message, to this object, array);
]]></ac:plain-text-body></ac:macro>
Dec 29, 2007
Maurice Fonk
<p>I like this proposal a lot. Imho the observer pattern is a very powerful and useful one, that has a place in a framework. The only thing that I'm not entirely sure about is the interface, it allows for just one method (notify()), where some people may rather see a callback.</p>
<p>You don't seem to be using SPL's observer class, is there a reason for this? </p>
Dec 29, 2007
Jurrien Stutterheim
<p>You got a point with the callbacks. I'll try took see if I can provide the callback functionality, but without making the component too complex for people who don't need it.</p>
<p>The SPL classes didn't fit the needs for this component (e.g. the extra argument in the addObserver method). </p>
Dec 29, 2007
Maurice Fonk
<p>callbacks as "optional" sounds great to me, I like the simplicity of the interface, and notify() (maybe with a simple switch) should be enough for most uses.</p>
Dec 29, 2007
Geoffrey
<p>Hi there, I'm very happy to see this proposal as I think it's something much needed in a framework. I have my own event handling implementation, and it's very close to the one proposed here, so I won't say I kinda like it (oops I said it), but I think it lacks some advanced feature to be really powerful:</p>
<p>The notification center could allow observers to register to more than one notification at a time. It could be achieved via a simple globing mechanism or by allowing the second argument to be an array:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
<?php
// imagine the Blog_Post model exposes the post.new, post.update and post.delete events
$postObserver = new Blog_Post_Observer;
$notificationCenter->addObserver($postObserver, 'post.*'); // globing example $notificationCenter->addObserver($postObserver, array('post.new', 'post.update')); // array example
?>
]]></ac:plain-text-body></ac:macro>
<p>of course the globing feature relies on a strict event naming convention. For the sake of keeping the api simple, when registering multiple events, the callback, if any, should be the same for all registered events.</p>
<p>The notification center could benefit from lazy observer loading. Imagine you register an observer for an event that will be triggered only under some circumstances so that the observer is not likely to be used each time the app is running. The addObserver could allow the first argument to be a string to deal with this:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$notificationCenter->addObserver('Blog_Post_Observer', 'post.*');
]]></ac:plain-text-body></ac:macro>
<p>The notification center would then instanciate the observer on the fly and only when needed, which could result in a performance gain.</p>
<p>Last, I'd like to throw in some random ideas:</p>
<ul class="alternate">
<li>should an event be cancelable by an observer ? this would prevent further propagation of the event</li>
<li>should an event be updatable by an observer ? like adding/updating/deleting data from it ? not sure it sticks with the spirit of the observer pattern tho.</li>
</ul>
Dec 29, 2007
Geoffrey
<p>the first example is all screwed up:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
<?php
// imagine the Blog_Post model exposes the post.new, post.update and post.delete events
$postObserver = new Blog_Post_Observer;
$notificationCenter->addObserver($postObserver, 'post.*'); // globing example
$notificationCenter->addObserver($postObserver, array('post.new', 'post.update')); // array example
?>
]]></ac:plain-text-body></ac:macro>
Jan 03, 2008
Jurrien Stutterheim
<p>Hi Geoffrey,</p>
<p>I played around with your ideas a bit and implemented the wildcard and array idea.<br />
Will update the proposal as soon as I clean up some of the code.</p>
Jan 03, 2008
Jurrien Stutterheim
<p>Forgot to reply on your random ideas last post.</p>
<p>In my opinion an observer should only receive a notification.<br />
Canceling and updating the notification would lead to big headaches when debugging your application I think.</p>
Dec 29, 2007
fc
<p>I've been doing some research and here are some observations: </p>
<p>1. We are dealing with an event notification system. That's how this type of component is better known in other languages. So, some possible names are: Zend_System_Event or Zend_Event. </p>
<p>2. Maybe Zend_Notification_Center can be called Zend_Event_Source? In Java for example, an event "listener" is an object that receives notification of events and an event "source" is an object that generates them.</p>
<p>3. addObserver() method can be renamed to registerEvent() for example, to keep it more consistent with other languages.</p>
<p>4. You might need an Event object implementing an interface. So you wrap the the observer object (or class name), the name, selector (or callback?) and inject it into Zend_Event_Source. This way users can extend the Event object.</p>
<p>5. postNotification(), is better known as postEvent() or sendEvent(). And keep in mind that post and send have different meanings.</p>
Dec 30, 2007
Jurrien Stutterheim
<p>I've been busy looking at the naming of some methods and their parameters (not yet committed to the proposal). Things are named a bit more natural now.<br />
I'm still not sure about the addObserver/removeObserver naming. The naming actually describes what it does pretty well. However, the SplSubject interface calls those methods attach()/detach().<br />
Although this interface is not used, it might be better for consistency to use the Spl naming. What do you think?</p>
<p>As for Notification vs Event: Notification describes a bit better what the component does, but that's just a matter of how you look at it I guess. But if more people think it should be called Event, I don't mind renaming <ac:emoticon ac:name="smile" /></p>
Dec 30, 2007
fc
<p>Hi Jurrien</p>
<blockquote>
<p>As for Notification vs Event: Notification describes a bit better</p></blockquote>
<p>Remember that I'm suggesting Event_Notification and not just Event <ac:emoticon ac:name="smile" /> An event can notify, log or trigger something, for example. </p>
<blockquote>
<p>SplSubject interface calls those methods attach()/detach().</p></blockquote>
<p>IMO you need to forget about the patterns that you are using and create an API based on the functionality that the component offers, so that way we can figure out what it does by just looking at the API. For example, you don't use getSingleton() to get an instance of an obj, you use a more descriptive name like getInstance(). Same for addObserver(), I think you should explain what the method does without specifying the pattern that you are using.</p>
<p>So, if you are going to add a notification, why call it attachObserver()? You can call it addNotification(), addEvent(), registerEvent() or something like that. It will give other developers a much better idea of what that method is doing.</p>
<p>For example:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class List implements Observable
{
/* @see Confirmation */
private $_confirmation = null;
public function addFriend($name)
public function addConfirmation(Observer $observer)
}
class Confirmation implements Observer
{
public function added($obj, $name)
}
$list = new List();
$list->addConfirmation(new Confirmation());
$list->addFriend('Maria');
]]></ac:plain-text-body></ac:macro>
Jan 02, 2008
Jurrien Stutterheim
<p>The attach() method doesn't actually add or register an event itself. Instead it registers an object TO an event. It lets the object listen if you will (maybe a method listen() or startListening() ?)<br />
The actual event gets instantiated and fired once each time post() is called.</p>
Dec 30, 2007
fc
<p>So, you could have event notifications, but also implement an interface in case someone wants to add another type of event in the future:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class Zend_Event {
}
interface Zend_Event_Interface {
}
class Zend_Event_Notification {
}
class Zend_Event_Trigger {
}
class Zend_Event_Logger {
}
]]></ac:plain-text-body></ac:macro>
<p>And following the CoffeShop example:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class CoffeeShop_Customer
{
public function __construct()
...
}
]]></ac:plain-text-body></ac:macro>
Jan 02, 2008
Jurrien Stutterheim
<p>I have a few question about your suggestion <ac:emoticon ac:name="smile" /></p>
<p>What would Zend_Event role be? What would be the difference between Event_Notification and Event_Trigger?<br />
Would it provide extra functionality that's not possible with the structure I'm describing?</p>
<p>My goal is to KISS with this component (sounds exciting, no? <ac:emoticon ac:name="wink" /> ). It should provide a simple means to use KVC for transmitting one or more objects. The actions that are taken with the received objects are outside the components scope, because it's almost always very specific for the receiver.</p>
<p>To take your example class structure and translate it how I see them:</p>
<ul class="alternate">
<li>The notification would be the notification sent by the Notification_Center</li>
<li>The Trigger would be the action taken in the object that receives the notification</li>
</ul>
<p>As for the logger... I was thinking about adding a catch-all notification for this sort of thing. If an object registers to the "<strong>" event (without the quotes of course) it receives all notifications that are sent. A logger class could register to "</strong>" and log the traffic : )</p>
Jan 02, 2008
Jurrien Stutterheim
<p>Oops... that should be the "*" event what I was talking about. (forgot to escape it :x)</p>
Jan 02, 2008
Geoffrey Tran
<p>I agree, naming should be more towards a nice API, getInstance(), etc.. Zend_Event_Notify.</p>
Jan 03, 2008
Matthew Ratzloff
<p>I don't know, Jurrien, I really don't see anything here that's not already covered by the SPL interfaces. The reason those interfaces don't have additional parameters is because the idea is for subjects to be able to report on their state via a <code>getState()</code> method.</p>
<p>In other words, when the <code>notify()</code> method is called for the subject, it iterates through its observers and calls <code>update()</code> on them all. Within each observer's <code>update()</code> method, they would typically call something like <code>getState()</code> to get any relevant state information, and then if necessary call any additional methods on the subject using that information.</p>
<p>So with no offense intended, I guess I'm having trouble seeing the value this proposal adds.</p>
Jan 03, 2008
Jurrien Stutterheim
<p>Hi Matthew,</p>
<p>No offense taken. I didn't expect to please everybody. <ac:emoticon ac:name="smile" /><br />
Still, please allow me to explain why I think the SPL interfaces just don't cut it for what I want to provide.</p>
<p>What you're describing is a typical "pull" implementation of the observer pattern. In the case of the pull observer the SPL interfaces are fine indeed. Their concrete implementation rely heavily on the Subject, which make a generic and flexible concrete implementation much harder to realize.</p>
<p>This however is a concrete "push" implementation of the pattern, which can be used in a more generic fashion. The Subject itself doesn't have a state that needs monitoring. It's only task is to relay complete notifications with useful information to the observers. Which observer receive a notification depend on which notification was sent (not every notification goes to all observers). This design has proven itself to be very useful in Cocoa programming and I can definitely see it proving itself in this framework.</p>
Jan 05, 2008
fc
<p>The idea is good, the only problem is the way you approached it. If you want to build a system that implements a complex network of interconnection between objects, you'll definitely need an Event Notification System, and ZF doesn't have one. But, in your proposal you are focusing to much on the observer pattern, and although the pattern is important, you need to focus more on what you want to achieve, and not how you want to achieve it.</p>
<p>I would change your example to something like this:</p>
<p>Classes:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class Zend_Event_Notify {
}
class Zend_Event_Notify_Request {
}
class Zend_Event_Notify_Response {
}
class Zend_Event_Notify_Response_Interface {
}
class Zend_Event_Log {
}
]]></ac:plain-text-body></ac:macro>
<p>Example: </p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class CustomerController extends Zend_Controller_Action
{
public function orderAction()
}
class CoffeeShopController extends Zend_Controller_Action
{
const ORDER_READY = 'order_ready';
const ORDER_ONHOLD = 'order_onhold';
const ORDER_CANCELED = 'order_canceled';
public function processOrder($order, $customerId)
{
$alertCustomer = false;
$data = array();
foreach ($order as $item) {
$data[$item]['price'] = $this->getPrice($item);
$data[$item]['stock'] = $this->checkAvailability($item);
if (! $data[$item]['stock'])
}
$manager = Zend_Event_Notify::getInstance();
if (true === $alertCustomer)
else
}
}
]]></ac:plain-text-body></ac:macro>
<p>The Customer object makes an order and requests a notification. The Coffee Shop processes the order and posts a notification. If an item is not available, the Manager of the Coffee shop is notified and the event logged. If all the items are available, then the Stock Manager is notified and the products restocked. </p>
<p>It might look silly when interconnecting 2 objects, like in the example above, but it's very useful when working with complex network of objects. </p>
Jan 16, 2008
Sebastian Krebs
<p>Ive to say, that i dont read the comments, but whats the matter of dont using the spl's Subject/Observer-Pattern?</p>
Mar 13, 2008
Ralph Schindler
<p>Jurrien,</p>
<p>Could you perhaps talk about practical use cases that this component attempts to provide for? The coffeeshop example is a bit to abstract for me to fully get a grasp on the problem area.</p>
<p>Just so you can see where I am coming from, I think the real reason why a push based notification system is not included in SPL is b/c it (on its own) is not condusive to the nature of php. What I mean by that, is since PHP is a build-up/tear-down environment (per request), and since its primary audience is the web, how does the observer pattern apply here? Is the thinking that it is more suited for CLI? If you are using this for a use case within a web application.. how is persistence handled (since for example, posting of a blog happens in a request different than a request receiving the notification that the even has happened).</p>
<p>Java is more suited for the observer pattern (specifically push based systems) since the application maintains its state within Java, where as PHP requires the use of application code (ext/session for example) to persist state.</p>
<p>Long winded I know, but figured I'd ask for some clairity in this department.</p>
<p>-ralph</p>
Mar 19, 2008
Jurrien Stutterheim
<p>Hi Ralph,</p>
<p>As we discussed on IRC I'm still trying to get you an example of real-life usage in a real-life project.</p>
<p>You are right in saying that an observer pattern makes more sense in a desktop app in general.<br />
However, I don't think this idea is misplaced in a web environment.</p>
<p>Let's take the bootstrapping process as example.<br />
At the moment the bootstrap file is the only place in a ZF app where a lot of pure procedural PHP is applied.<br />
The order in which components are instantiated and linked together actually matters in this process.<br />
<a href="http://www.zym-project.com/">Zym_App</a> tries to solve this problem by abstracting the bootstrapping process and allowing the developer to configure the bootstrap (if needed) by using configuration files.<br />
A problem that arises with such a complex component is that various components depend on each other.<br />
Zend_Db_Table_Abstract (ZDTA) is a nice and simple example of this. In order to enable caching for ZDTA, you would need a cache instance. Ideally you want to keep cache and db config separated so the configs can be reused in different apps (An app might need caching, but not the db or vice versa for example).<br />
The class responsible for setting up ZDTA could in this case register to an event called 'CacheIsAvailable' (let's assume that this is the name of the notification the cache setup class sends after it's done creating a cache instance). Now ZDTA can be setup without having a cache instance. However, when the cache instance is available, it gets set in ZDTA to cache metadata.<br />
Example code (not the real zym_app code <ac:emoticon ac:name="wink" />):</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class SetupDb
{
public function __construct(Zend_Config $config)
{
if (!Zend_Registry::isRegistered('cache'))
else
$db = Zend_Db::factory($config);
Zend_Db_Table_Abstract::setDefaultAdapter($db);
}
public function notify(Zend_Notification_Message $message)
{
// alternatively, we could've include the cache instance in the message
if ($message->getName() == 'CacheIsAvailable')
}
protected function _setupFromRegistry()
}
class SetupCache
{
public function __construct(Zend_Config $config)
}
new SetupDb(new Zend_Config_Xml('dbconfig.xml'));
new SetupCache(new Zend_Config_Xml('cacheconfig.xml'));
]]></ac:plain-text-body></ac:macro>
<p>The nice thing here is that the cache setup doesn't need to know it has to be set in ZDTA, so no require_once for ZDTA is needed.<br />
Also, it doesn't really matter in which order the resources get setup this way.</p>
<p>Hopefully this will clear things up a bit <ac:emoticon ac:name="smile" /><br />
As for your idea on using sessions, I still have giving that more thought on my todo list.</p>
<p>Cheers</p>
Jun 15, 2008
Matthew Ratzloff
<p>A few suggestions...</p>
<p>1. The existence of the interface is a bit odd, since you can set your own custom callback method. I don't think it adds a lot of value. I would require a callback method to be specified (no default) and ditch the interface altogether. Actually, the default callback notify() is detrimental because it will confuse users who expect the subject to do the notifying (the standard Subject/Observer nomenclature).</p>
<p>2. I would replace all the get()/remove()/has() methods with a simple getInstance(). Don't worry about namespaces unless users request it down the road – it would be an easy thing to add in later. If you think namespaces are important, I think a use case would be helpful to demonstrate why.</p>
<p>3. Everyone seems to have naming suggestions, but here's mine:</p>
<ac:macro ac:name="tip"><ac:rich-text-body>
<p>Zend_Message (from Zend_Notification_Message)<br />
Zend_Message_Dispatcher (from Zend_Notification)</p></ac:rich-text-body></ac:macro>
<p>I think that most clearly communicates the purpose of the class.</p>
<p>4. Your current API does not account for the possibility of a simple function callback. Doing so would be easy and would be in line with standard PHP behavior regarding callbacks.</p>
<p>Object oriented:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
// class My_Observer
$messageDispatcher = Zend_Message_Dispatcher::getInstance();
$messageDispatcher->attach(array($this, 'update'), My_Subject::EVENT_MODIFIED);
// Alternately, $this can be a string for static callbacks
]]></ac:plain-text-body></ac:macro>
<p>Functional:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$messageDispatcher = Zend_Message_Dispatcher::getInstance();
$messageDispatcher->attach('doSomething', My_Subject::EVENT_MODIFIED);
]]></ac:plain-text-body></ac:macro>
<p>5. Rename post() to notify(). That's the standard nomenclature.</p>
<p><ac:emoticon ac:name="smile" /></p>
Jun 16, 2008
Jurrien Stutterheim
<p>Hi Matthew,</p>
<p>1. The interface is to avoid calls to method_exists() when possible. It's an approach I find much cleaner. Then again, it does create inconsistency when using an alternate callback method. I'm gonna consider removing the interface.<br />
To keep things simple (or at least to few characters) I'm gonna keep the default callback method. Do you have a naming suggestion?</p>
<p>2. The namespaces were a feature request from someone. However, I can't remember why exactly he needed it. Gonna see if my IRC logs can help me out on that one.</p>
<p>3. I like the Zend_Message naming suggestion. It's shorter and easier to type and it still describes the component pretty well.</p>
<p>4. To be honest, I don't see the benefit of having a function callback option. Also, the use of regular functions is discouraged in ZF. Could you give me a usecase for this?</p>
<p>5. Actually, the SPL interfaces use notify() for the subject. I wanted to keep naming familiar. That said, I do kinda agree with you on the naming of post() and the default notify() methods. Then again, to post a message does sound good. Or to send...</p>
Jun 18, 2008
Matthew Ratzloff
<blockquote><p>4. To be honest, I don't see the benefit of having a function callback option. Also, the use of regular functions is discouraged in ZF. Could you give me a usecase for this?</p></blockquote>
<p>Well, a primary reason is consistency with PHP, and therefore an intuitive API for users. But your API also does not allow for static callbacks. And if you're going to make that possible, you might as well just make it follow the standard PHP practice for method signatures with callback parameters.</p>
<p>This form of callback is even defined as an official "pseudo-type"; see <a href="http://www.php.net/callback#language.types.callback">http://www.php.net/callback#language.types.callback</a>). Regardless, more flexibility, as long as it's not a detriment to the functionality or maintainability of the component, is never a bad thing.</p>
<blockquote><p>5. Actually, the SPL interfaces use notify() for the subject.</p></blockquote>
<p>But that's what I mean. Currently in your example you have the observer declaring a notify() method, with that as the default callback. Only the subject should notify() its observing classes by calling update() (see <a href="http://www.php.net/~helly/php/ext/spl/interfaceSplObserver.html">SplObserver</a>) on each of them.</p>
<p>In other words, Zend_Message_Dispatcher is acting as a proxy subject in this context, so the method currently named post() should be notify(). And therefore in answer to your first point, if you were to include a default callback name it would be update(). However, I'm still in favor of no default method name.</p>
Jun 18, 2008
fc
<p>@Ralph: Java is more suited for the observer pattern</p>
<p>Not really. Event notification systems are language agnostic, the play a fundamental role in, for example, a plug-in architecture. The host usually manages registered plug-ins, which can request notification from the host and act on certain events. Although it's optional, I've never implemented a plug-in architecture without using the observer pattern. </p>
<p>@Matt: 3. I like the Zend_Message naming suggestion. </p>
<p>Zend_Notification<br />
Zend_Message_Notification<br />
Zend_Event_Notification</p>
<p>Isn't message to generic?</p>
<p>@Matt: 5. Rename post() to notify()</p>
<p>I'm in favor of using notify() as well.</p>
Jul 30, 2008
fc
<p>I still think Message it to generic and has different meanings, see <a href="http://en.wikipedia.org/wiki/Message_passing">Message passing</a></p>
<p>As you may now, Symfony 1.1 introduced an event notification system inspired by Cocoa, although I want to believe it was inspired by Jurrien <ac:emoticon ac:name="wink" /></p>
<p>The API is very simple, it consists of 2 classes, Event and EventDispatcher:</p>
<ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
class sfEvent implements ArrayAccess
{
public function __construct($subject, $name, $parameters = array())
{}
public function getSubject()
{}
public function getName()
{}
public function setReturnValue($value)
{}
public function getReturnValue()
{}
public function setProcessed($processed)
{}
public function isProcessed()
{}
public function getParameters()
{}
public function offsetExists($name)
{}
public function offsetGet($name)
{}
public function offsetSet($name, $value)
{}
public function offsetUnset($name)
{}
}
class sfEventDispatcher
{
public function connect($name, $listener)
{}
public function disconnect($name, $listener)
{}
public function notify(sfEvent $event)
{}
public function notifyUntil(sfEvent $event)
{}
public function filter(sfEvent $event, $value)
{}
public function hasListeners($name)
{}
public function getListeners($name)
{}
}
]]></ac:plain-text-body></ac:macro>
Sep 11, 2009
Marco Kaiser
<p>When comes this Proposal to the Labs or Release? I have my own implementation or plan to write a own Proposal or maybe take this over if the proposer is inactive.</p>