I'm currently implementing the Observer design pattern and using it to handle adding items to the session, create error logs and write messages out to the user giving feedback on their actions (e.g. You've just logged out!).
I began with a single method on the subject called addEvent() but as I added more Observers I found that the parameters required to detail all the information I needed for each listener began to grow.
I now have 3 methods called addMessage(), addStorage() and addLog(). These add data into an events array that has a key related to the event type (e.g. log, message, storage) but I'm starting to feel that now the subject needs to know too much about the listeners that are attached.
My alternative thought is to go back to addEvent() and pass an event type (e.g. USER_LOGOUT) along with the data associated and each Observer maintains it's own list of event handles it is looking for (possibly in a switch statement), but this feels cumbersome. Also, I'd need to check that sufficient data had also been passed along with the event type.
What is the correct way of doing this?
Please let me know if I can explain any parts of this further. I hope you can help and see the problem I'm battling with.
Related
I haven't seen anyone doing this, so i'm bit confused if it can be good approach.
Some small system with login. And i have simple group management withing that system. I want to be able to easily set and execute some triggers depending of action and on group in which user belongs.
First idea that came to my mind is to have in groups table 4 fields for triggers, named like this:
add_triggers (when user is added to trigger this)
delete_triggers (when user is removed from a group)
login_triggers (when user logs in to be triggered)
logout_triggers (when user logout to be triggered)
Now i'm wondering how to relate that to an actual trigger code?
Should i have separated class triggers that should receive just "names" of triggers and in that class to hold all possible trigger's code? So that i'm able to execute that in some kind of a loop?
Does anyone have any other idea how to organize that?
p.s. those groups are quite an important part of a system. Most of the things should be based on them. They even has extending tables for complex type of groups.
thnx
What your looking for is Laravel Events.
I would definetly recommend making a class that the event calls rather than writing procedural style code.
Event::listen('auth.login', 'LoginHandler#onLogin');
Foreword: The following text is of decent size, because I tried to maximize the value to other readers with similar, fundamental and conceptual questions.
Introduction
Currently I am developing an web-based event management tool, which uses the Laravel MVC framework to maintain a proper application structure and ease development.
The goals targeted with the application are to
provide a efficient way to create (respectively CRUD) events
invite registered users to those events
allow users to confirm their participation on previously created events
Following the MVC-Pattern, I created
a Model named Event
a EventController
multiple views
a static event view, displaying already existing events
a form view for creation and editing named eventForm
eventIndex, a list of all events
Up to this point, everything seemed to be relatively straight-forward, but I ran into design problems, when I tried to implement further functionality to allow users to confirm their participation on specific events.
Further Details
For further clarification, each Event has a number of attributes (some omitted):
Title
Description
Multiple EventDates, consisting out of this attributes:
Title
A timespan (for example 09-20-2013 09:00 AM to 09-20-2013 05:00 PM)
The aforementioned EventDate is also a model with an associated database table.
Distinguished by the account a user is logged in with, I made a boolean variable $admin available to all views and controllers, which is used to alter the view event in the following way:
$admin = true: The view is a static page, showing the Events attributes and EventDates in a table
$admin = false: In addition, the view has a hidden form and buttons for each EventDate table row, allowing the users to confirm or decline their participation on each of the EventDates
Using a variable and #if...#endif-blocks to alter the view seems acceptable to me, as, despite of the hidden form, the differences between User-Mode and Admin-Mode are quite small.
The Problem
Now, the problem I am stuck at, is the following:
Who is responsible for processing the POSTed data of the User-Mode hidden form?
At first, here a few facts to the current development state:
The Event controller currently offers the following functions:
/* CRUD functions */
public function CreateEvent()
public function ShowEvent($id)
public function UpdateEvent($id)
public function DeleteEvent($id)
/* Form display helpers */
public function NewEvent()
public function EditEvent()
The EventDate Model is separate from the Event Model, as a Event has multiple EventDates
Confirmations are stored per user and EventDate in another separate table bound to the EventDateConfirmation model
Solution approaches
These are the options I have thougth of:
The EventController, which must be extended with methods like CreateEventDateConfirmation() and so on, leading to multiple CRUD methods, which not even belong to this controller, as they are not directly regarded to the Event model and no change at all happens in the events table
In a separate EventDateConfirmationController, only responsible for getting and setting the EventDateConfirmation model data, with two usage possibilities:
Calling the EventDateConfirmationControler methods from the EventController by using the somewhat clunky
Controller::resolve(DEFAULT_BUNDLE,'EventDateConfirmationController')->CreateConfirmation($params);
Setting the route which responds to the hidden form POST-request to the corresponding EventDateConfirmationController action directly
The first possibility has the disadvantage of calling an external controller in a unpleasant way which seems wrong to me, the second is not practicable when the form also contains data which belong directly to a event and therefore must be handled by the Event controller
??
In my opinion, neither #1 nor #2 are good solutions to the problem, as they seem to be hack-ish and do not fit very well in the MVC-pattern.
What alternatives are available, which would be a clean solution to this problem?
Thank you in advance!
I think you might be able to do #2 and make it a little less hackish but still not have to change much from before. Otherwise I think #1 is not a good choice.
Realistically what I would do if I were in your circumstance is create the EventDateConfirmationController and in the User-Mode view, make it a separate form that is asynchronous ajax. Either submit the form when the user clicks [assuming] the checkbox that he/she is going, or on when they submit the other form.
I definitely feel like javascript can help you keep your code consistent and still MVC like.
I've read some guides / tutorials about Symfonys event system. But I am still not sure about the naming best practice. Unfortunatelly most documentations use default scenarios like login, etc. So here is an example from a game:
A command evaluations some kind of match result. It fires an appropriate event like this:
$dispatcher->dispatch('game_bundle.match_won', new MatchWonEvent($match, $winner));
Now I want to register several listeners to handle this event, like for example one for posting this to the winner's Facebook page and another one to book an achievement for the winner. In the examples I found the listener handling the login event was mainly called something like LoginListener, but shouldn't this name relate to the actual use of it instead of the event it is related to? Because now in my example I would need a MatchWonListener, but should that contain both the Facebook and the achievement logic? That would make the event system useless then... Wouldn't it be better to have one FacebookListener with an onMatchWon($event) and one AchievementListener with it's own onMatchWon($event) method? This would also make it easy to add more Facebook-related events into the FacebookListener for example.
I am confused about the naming in the samples and not sure about now. Am I getting it totally wrong?
There's no "best practice" on how to name events. However, if you name the listener after the event, I think that defeats the purpose of events altogether. The goal is to be able to let different parts of your system interact between each other without coupling and mixing concerns.
So considering you went this far of creating events to separate concerns, why would you go and mix all the different logics into one listener? In that case you might as well just do a direct call instead of dispatching an event.
I'm personally against names like "onMatchWon" because that doesn't describe what the method does. Let's say you want to listen to a match won event and update the achievements of the user who won. I'd probably have some user manager service or the sort with a method updateAchievements(MatchWonEvent $event). But I think that's more of a matter of taste, or convention if you're willing to.
The very basic idea of my goal is this:
User A submits a value via a form to submit.php
User B monitors the values submitted, which is updated via Server-Sent Event, pushed from updates.php.
submit.php handles writing the new value to the database, as well as notifying the observer object in updates.php.
Points of confusion:
Does each instance (session) of updates.php needs its own observer, as each user viewing the updates will be running their own instance of the script, or can they all share the same global observer object?
When the Subject Object loads, where is it going to get the observer objects? I can't store/put to sleep the observers, as they are active, right?
If I go with an ObjectStorage object, when the submit.php gets called and fetches it, are they observer objects actually the observer objects, by which I mean will calling their update method actually update the user's list?
How does I store/retrieve the ObjectStorage object from submit.php each time the form is submitted? Obviously I can't uses sessions, right? As those would be per-user?
Short version: Is there a way to get a global, persistant object containing the Observers on the Subject side where the Observers are live objects?
If there are better or simpler approaches to this idea (or if I'm just totally confused and need educating) please let me know. But I am not looking for a framework that can already do it all, as I'm trying to use this project to better understand the Observer pattern as an idea.
An important note for you to remember before the explanation:
A design pattern is a solution created to solve a specific language-related problem (limitation). They are not design rules of thumb in software architecture at a language level.
I'm not sure on how you can see the Observer pattern, but I'll try to help you anyways:
No. Session in your case means user instance. You should, somehow, work with single abstract Observers that will handle all the instances of updates. The global Observer object is the way to go;
Yes, they are active objects, since the Observers register themselves with the Subject. At some point you are gonna have to intercept them;
Whenever the Subject changes, it broadcasts to all registered Observers that it has changed, and each Observer queries the Subject for that subset of the Subject’s state that it is responsible for monitoring. I guess you can figure that out from that;
That's really about implementation design. There is not a specific way to do it. You can try and see what suits you better;
Basically, yes, you can have a global Observer object, but that's not really the point of the pattern.
Try reading about the implementation of the Observer pattern and see if that helps you at all.
I would suggest that you investigate socket.io.
An Observer Design Pattern is the solution to loosely coupling objects so they can work together. In PHP you can easily implement this using just two classes.
Basically, you have a subject which is able to notify and update a list of observers of its state changes.
The problem I'm trying to solve is to know how to handler alerting the observers about different states of the object they are watching.
For example, lets say we have a file upload class to which we attach a logging class, websockets class, and a image resize class. Each of these classes that are watching want to know about different events in the upload process.
This file upload class might have three places where it needs to notify the classes listening that something has happend.
Error With Upload (alert logging class)
Upload success (alert websockets class)
Upload success and is image file (alert image resize class)
This is a very basic example, but how do you handle multiple events that different observers may need to know about? Calling notifyObservers() alone wouldn't be enough since each observer needs to know what it is being notified about.
One thought is that I could state with the call what type of event is being observed:
$this->notifyObservers('upload.error', this);
However, that would mean I would have to add custom switching to the observers themselves to know how to handle different events.
function observe($type, $object)
{
if($type === 'upload.error') $this->dosomething();
elseif($type === 'something.else') $this->otherthing();
...etc...
}
I find that very ugly as it starts to couple the observers back to the class they are observing.
Then again, if I just notify Observers without passing any information about what event just happens - they have to guess themselves what is going on which means more if() checks.
The observers aren't actually coupled to the class they are observing. The connection between the observer's handler and the observed object is made using literal string values (e.g. `upload.error'), which means that:
If you want to observe a specific object, you have to know from beforehand the names of the events it will publishing; this is the "coupling" that you don't like.
On the other hand, if you are interested in a specific event only, you can observe any type of object for that event without having any knowledge about that object.
Item 2 above is a benefit that you care about, but what to do about item 1?
If you think about it, there needs to be some way to differentiate between callbacks to the same observer if they represent different events taking place. These "identifiers", no matter what form they take, need to be packaged either into the observed object or be a part of the observer library code.
In the first instance (inside observed object) you would probably need a way for observers to query "do you ever publish event X?" before starting to observe a target for that event. The target can answer this question just fine. This leaves a bitter taste of coupling, but if you want any object to observe any other, and you have no idea what you will be observing beforehand, I don't think you can do any better.
In the second approach, you would have a number of well-known events defined (as const inside a class?) in your library. Presumably such a list of events can be made because the library tackles a concrete application domain, and that domain offers obvious choices for the events. Then, classes both internal to your library (which would end up being observed) and external to it (the observers which plug into the framework) would use these identifiers to differentiate between events. Many callback-based APIs (such as Win32) use an approach practically identical to this.