4

所以事件链是:

  1. 用户提交表单。
  2. 在处理提交的过程中,会生成一条消息,例如“您的记录已保存”。
  3. 用户被重定向到一个新页面,比如搜索结果。
  4. 新页面需要显示消息。

那么,问题是如何从第 2 步到第 3 步获取消息?这只是一个简单的例子……还有许多其他更复杂的例子。

我正在使用 PHP。

需求:

  • 支持多条消息,需要在接收机器上按要求进行格式化
  • 可以在同一页面上添加消息(例如在第 4 步中)
  • 从任何函数或对象内部添加的消息

我想出了一些选择:

  • 以数组形式存储在会话变量中,并在每次显示后清空
  • 作为获取或查询参数传递;当您不断处理此问题并且必须记住要获取它时,可能会很烦人;因为它可能会变长,它很容易超过查询字符串的最大长度
  • 在每个会话的基础上存储在数据库中(可能并不总是用于登录用户);这将需要在添加它们的每个页面上进行额外的插入,可能是多个插入,并且在每个页面上进行额外的选择

目前我一直在将会话中的消息存储在一个数组中,但我想知道是否有更好的方法。我不认为上面的其他 2 个选项非常好。

编辑:我对会话方法使用 2 个函数:AddStatusMsg()(将元素添加到数组)和 DisplayStatusMsg()(返回 HTML 格式的消息并清空数组)。

4

9 回答 9

6

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.

于 2008-11-20T03:42:15.800 回答
3

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.

于 2008-11-20T02:22:25.367 回答
3

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.

于 2008-11-20T02:34:24.330 回答
1

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.

于 2008-11-20T03:29:11.927 回答
1

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'.

于 2008-11-20T04:04:00.687 回答
0

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).

于 2008-11-20T02:22:40.673 回答
0

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.

于 2008-11-20T02:24:43.430 回答
0

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.

于 2008-11-20T02:29:36.087 回答
0

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.

于 2008-11-28T21:24:15.440 回答