views:

299

answers:

9

So the chain of events is:

  1. The user submits a form.
  2. During the processing of the submission, there is a message generated, such as "Your record was saved."
  3. The user is redirected to a new page, say the search results.
  4. The new page needs to display the message.

So, the question is how to get the message from step 2 to step 3? This is only one simple example...there are many other much more complicated examples.

I am using PHP.

Needs:

  • supports multiple messages and need to be formatted on the receiving machine as required
  • messages can be added on the same page (such as within step 4)
  • messages added from inside any function or object

Some options I have come up with:

  • store in a session variable as an array and emptied after each display
  • pass as a get or query parameter; can get annoying as you are constantly processing this and have to remember to get it; as it can get long, it could easily go over the max length of the query string
  • store in the database on a per session basis (may not always be for a logged in user); this would require an extra insert on each page where they are added, possibly multiple, and an extra select on every page

Currently I have been storing the messages in the session in an array, but I'm wondering if there is a better way. I don't think the other 2 options above are very good.

Edit: I use 2 functions for the session method: AddStatusMsg() (adds an element to the array) and DisplayStatusMsg() (returns an HTML formatted message and empties the array).

+3  A: 

I would stick with the session approach only perhaps adding support for this messaging system on the master page. You are on the right way as the all other approaches have a greater cost, of simplicity or performance.

I suppose you have a master page which is the template for all other pages. If you don't have it's a good reason to have one, so you don't need to take care of handling the displaying of the messages on every page you need it as long as you have a specific place to show them.

You can also use a specific div rendered by the master page for that and let the position be handled by the current page. If I understand correctly you need some kind of timing between the showing of the message and the user redirection to another page. This could be achieved using any AJAX library to show that div I said before and then redirecting to a new page.

I suggest taking a look into jQuery.

Augusto Radtke
In most cases the message should be there for a long time, versus 10s seconds and then redirect.
Darryl Hein
You can probably make a helper class and classify the messages by type, which some will render timed redirect scripts and others don't.
Augusto Radtke
Usually the redirection is not based on the message. It's usually based on errors, the data entered or the button/link pressed. Trying to put all of that into a class could be a bit hairy.
Darryl Hein
A: 

Store it in the database as well as the session. This way the user can get to his history if he needs it, and you have easy access through the session data.

Don't use a query parameter, it'll only confuse the user at some point when the message is displayed when it shouldn't be.

Displaying the messages should be a part of your main template (in other words; done once).

I would make it part of the template, but there are often pages on different sites where I don't want a message to be displayed or I want them in a different position within the content.
Darryl Hein
A: 

Maybe a slight improvement would be to store, instead of an array, an object's instance that gets populated and knows how to display the messages appropriately, deleting the data itself after any display routine gets called. That way you don't have to repeat the display and delete logic everywhere, plus, you can code different output routines in the object depending on the need.

Vinko Vrsalovic
A: 

I think you're doing it the right way. You should stay away from the database for this and putting it in the URL is ugly. You could write a nice little class for this which can make it simpler.

Here's a little session class:

<?php class session

{

public function __construct()
{
 session_start();
}

public function set($name, $value)
{
 $_SESSION[$name] = $value;
}

public function get($name)
{
 return (isset($_SESSION[$name])) ? $_SESSION[$name] : false ;
}

public function delete($name)
{
 unset($_SESSION[$name]);
}

public function destroy()
{
 $_SESSION = array();
 #session_destory();
 #session_regenerate_id();
}

}

A little message class can be built on that pretty easily.

dylanfm
I'm not sure a session class would be very useful. It just adds an extra layer onto already great php session functions.
Darryl Hein
True. I think I got a little carried away :)
dylanfm
+1  A: 

This is how I like to do it:

function set_message($message_type, $message)
{
    $_SESSION['messages'][$message_type][] = $message
}

function get_messages()
{
    $messages_array = $_SESSION['messages'];
    unset($_SESSION['messages']);
    return $messages_array;
}

where $message_type can be "warning", "error", "success", etc. and depending on the type you can show the user a different image/color/whatever.

Murat Ayfer
I do like the message type...maybe I should add that. Also, if you are unsetting the message key, you should probably check if the if it's set.
Darryl Hein
A: 

This problem is a classic example of how to have data persist in a "stateless protocol" like http.

Your options are:

  1. Pass it in the GET parameters (not user friendly)
  2. Store it in the DB
  3. Store it in Session

Options 2) and 3) require the user to have a cookie (otherwise, there's no way to match the user to the message). Between them, I'd go with PHP's built in sessions. Simply set a session variable at your step 2, and have the search page always check for the variable in your step 4

Nothing to it. Don't over complicate things.

+3  A: 

I would recommend AGAINST storing these messages either in the database or in the session, for one simple reason: tabs. (Well, really, the stateless nature of HTTP.)

Think of a person who's got multiple tabs open of different sections of your website. This person performs some action and while that loads, switches to another tab and clicks on a link. If you're storing the messages in the session/database and the switched-to tab is a page that can display these messages too, the user has now entered a race condition where depending on which request the server responds to first, the messages may display where they were not intended.

Now, there are some situations where this legitimately might not matter, but it could also be extremely confusing in some cases.

Putting the messages in the request doesn't have to be as bad as it initially seems. Perhaps you could store all the messages you want to display in the database with a numeric (or, for bonus obfuscation, hash) ID, and pass a list of IDs in the query string. This keeps the query string short, and all you have to do is keep track of what ID corresponds to what message in your code.

chazomaticus
How would you recommend ensuring you always have the hash or id?
Darryl Hein
Presumably, you'd add them to the database as you were coding it, and the table wouldn't change over the run of the application. You'd just have a config file somewhere that maps message "save_failed" (which contains some arbitrary error message) to ID 3, for example.
chazomaticus
Ops, I was meaning ensuring it's passed between the pages in the get or post. Not all the forms are automatically generated.
Darryl Hein
If you're redirecting after processing, you've just got the GET vars to work with. You could just keep a global array of messages to display on the next redirect, and make a redirect function that automatically adds those to the end of your URL. You could do similar things in other situations.
chazomaticus
+1  A: 

Probably the best way is to store it in the session. It's the simplest way and as John said, 'Don't over complicate things'.

Thorpe Obazee
A: 

I'm at this crossroad myself and I've considered all options extensively.

  1. How about storing two browser cookies, one called page and the other called message.
  2. On redirect you overwrite the cookie.
  3. When the page loads you check if said cookie exists (in the http headers sent by the client).
  4. Check if it's for that page, if it is, store the message in a variable and unset the cookies.
  5. If it's not for that page, ignore it, it will be output on the other tab that is loading or if it is for a page that for some reason never unset the cookie it will eventually expire.

This avoids using the database and session cookies.

Jay