在下正用PHP和Mysql开发个论坛系统,其中包含了"message"系统,即消息系统,用于站内用户之间的互动交流,用mysql来储存用户之间的消息记录,用户可自由发送,接收,删除任何邮件消息.这时,我突然想到,如果是以管理员(系统公告)方式发出的邮件,该如何实现判断"已读,未读"还有"删除"这一功能呢!?我有想到几点方案:
1.如果以每个注册用户一封邮件消息的形式的话,是行得通的,但是,假设有10W个用户,那么,mysql数据库一下子得多增加10W条相同的消息.太浪费储存空间了.
2.在message数据表中,多添加个字段,用于储存阅读了邮件消息的用户ID,来判断已读,未读.多添加个字段,用来储存删除了该公共消息邮件的用户ID.但是,这方法也太麻烦了,而且用于sql的查询语句极其不方便.
3.多增设个公告消息的数据表,但这么一来,每次都必须查询两次,一次私人信件的,一次公共信件的,对程序和服务器负担也挺大.另外,假设说,论坛增设等级制度,每次升级,都向该升级用户发送一封升级通知邮件,那么,这又该如何实现呢...小小的消息系统,看来文章还挺大的...熬夜到现在,实在受不了了,上CSDN上求救了,请教各位高手意见.有任何思路,都可以说一下,皆可得分.

解决方案 »

  1.   

    建议参考一下DZ的代码。它也是用的PHP+MySQL
      

  2.   

    1 消息对接收方和发送方都是唯一的,尽管不同的接收方可能会有同样的内容.
      所以对于收件箱的消息,分为两种,一种是私人消息,是一对一的,一种是公共消息,是一对多的. 
      但为了简化处理,可以都当做一对一处理.
    2 如果将消息都当做一对一来处理,为了记录消息的状态(未读,已读,已删除),只需要在消息后加上消息状态就可以了,这样是最简单的.
      但后果就是对于公共消息来说,可能会产生冗余信息.
    3 如何避免冗余信息?
      其实一封消息对于发送方要保存在发件箱,对于接收方要保存在收件箱.
      所以可以制定一个策略.
      a 发送信息只保存在发送方的发件箱里,对于接收方而言,可以保存发送方的消息ID.
      b 发送方删除信息时,如果接收方消息未删除,修改信息状态为已删除,并不真正删除.
        接收方删除信息时,直接删除消息.并查询发送方的信息状态,如果状态为已删除,再进行真正意义上的删除.
      

  3.   

    就用一个message表就可以了,包含字段:发件人,收件人,标题,消息内容,消息状态。
      

  4.   

    下个源代码程序下来研究一下 http://www.osphp.com.cn/index.php
      

  5.   

    实际上是对数据库建表的思路,同意楼上说的,不管公或私或什么,只是添加字段。对冗余信息按时间来删除,所以你每条信息因该都有时间。
    对已读和未读也是加字段,设为bit,0或1,第一次访问,把0改成1,再做个判断验证用户是0或1。
      

  6.   

    个人见角:应该建两个表:
    message(id,sendUser,requestUser,title,content,isRead,sendTime)
    message_sys(id,sendUser,requestUserId,title,content,sendTime)(1)对于系统信息:每次发送系统信息时在message_sys新增信息,如果哪个用户已读,便在requestUserId里新加用户id(用|或,或其它分隔)。
    想法:这样做,系统信息的条数不会太多,查询也便不慢,省空间又省时间。
    (2)升级时通知:应该在message里新增了,sendUser为系统管理员即可。
      

  7.   

    我不太同意5楼的观点
    如果发方删除 收方未删除呢
    你后面说的当双方都删除 才真正删除 是没错的 但之前的表述就不对了 不能说信件只存在发放信箱 收方存个ID就行了站在巨人的肩上 表述一下我的想法:
    还是只用message一个表 每条记录一个信件 存有发者ID和收者ID 收发查询时查等ID的集合就可以了
    对于系统消息来说 只需要将发者和收者的ID都设置成0就行 只需要在SQL语句的WHERE后面加上 "OR 发者ID=0" 就行剩下的工作就交给PHP语句来实现
    还有楼主还需要考虑好友群发的实现方式 我的意思是在收着ID栏中将所有收者ID用"|"号隔开保存 在收件人查询语句中将"="号用"like"代替 就可以了
      当然也不能完全代替 在收者ID前后还要一边加上一个"|"号  不然连不该收的都收到了
      

  8.   

    另外列一张表出来就可以了,专门用来存储公告之类一对多的状态id int,msgid int/*信箱里面信息的id*/,status enum('N','R','D')/*n代表new 新信息,r代表已读,d代表删除了*/,uid int/*收信人id*/表比较小,就算百万级的存储也没什么关系。查询就可以联表查询。
      

  9.   

    一个message表就可以了,包含字段:发件人id,收件人id,标题,消息内容,消息状态 (0/1/ 已读/未读),发送者已删除 (0  未删 1 已删),接收者已删除(0 未删 1 已删)
    系统公告 就收件人id为0 到时查收信箱时  加个 or id=0
      

  10.   

    支持这个!
    Messages id
    content
    from_id   user_id/0
    to_id     user_id/0
    is_read   0未读/1已读
    is_delete 0未删/1接收方删/2发送方删/完全删除

     
      

  11.   


    呵呵...其实,我的一个方案中,就是这样的,假设收信人为all的话...之类的...不过,这样一来,就是必须多出个字段.用来储存查看了系统消息的用户的ID,用逗号或者|之类的来划分ID,简单的说,就是一个数组.不过,我们可以想像,假设说,是一封注册欢迎信件,用户注册后即发送,你可以想像一下这个数组的庞大.
      

  12.   

    from_id  user_id/0 
    to_id    user_id/0 就事论事,设计数据库不要相当然.
    这只是一对一的,是最普通的方式.
    你有没有考虑,单个用户群发给多个人的哪种的情况呢?
      

  13.   

    http://www.javaeye.com/topic/482182 我的方案之所以这样将信息主体与发件和收件分开,是因为信息主体表通常会很大,而且我们大多时候都是在查看列表,没有去查看信息的内容.所以分开对查询性能有很大的提升.