php mysql 中的消息系统

Messaging system in php mysql

我在我的网站上创建了一个简单的消息传递系统,新注册用户可以在其中相互发送消息。以下 mysql 语句在我的网站上运行良好,但是 我的问题是-UserAUserB 发送消息时,消息显示给 UserB 在他的收件箱中,并且消息显示给UserA 在他的发件箱中,现在如果由于某些原因 UserB 从他的收件箱中删除了邮件,那么邮件从双方都删除了,我将所有邮件存储在 1 个表中,现在我想要实现的是 当邮件从收件箱中删除时,它仍应保留在发件箱中,非常感谢您的帮助!谢谢!

表结构如下

id   message    sentby   sentto    created

Inbox.php

$you=$_COOKIE['username'];     
$st= "SELECT* FROM mbox WHERE sentto='$you' ORDER BY ID DESC LIMIT 10";

outbox.php

$you=$_COOKIE['username'];
$st= "SELECT*FROM mbox WHERE sentby='$you' ORDER BY ID DESC LIMIT 10";

您可以将 "status" 这样的列添加到 mbox table,

然后;如果 UserB 删除了您可以将状态更改为 1 的消息,或者 UserA 删除了您可以将状态更改为 2 的消息。

对于收件箱:

$you=$_COOKIE['username'];
$st= "SELECT* FROM mbox WHERE sentto='$you' AND status <> '1' ORDER BY ID DESC LIMIT 10";

对于发件箱:

$you=$_COOKIE['username'];
$st= "SELECT* FROM mbox WHERE sentby='$you' AND status <> '2' ORDER BY ID DESC LIMIT 10";

祝你好运。

添加一个像 has_mail 这样的列,它有像 AB 这样的默认值,这意味着两个用户都有邮件。现在,如果有人从他们的 in/out 框中删除,那么特定的 A/B 将被删除。

$st= "SELECT* FROM mbox 
      WHERE sentto='$you' and has_mail LIKE '%". $you . "' ORDER BY ID DESC LIMIT 10";

$st= "SELECT* FROM mbox 
      WHERE sentby='$you' and has_mail LIKE '". $you . "%' ORDER BY ID DESC LIMIT 10";

现在您可以在两个字段都为空时从数据库中删除消息:

DELETE FROM mbox WHERE LENGTH(has_mail) < 1 

不是从数据库中删除消息,而是使用该特定消息的状态
As SHOWtoSender,SHOWtoReciver,SHOWtoBothSHOWtoNONE
使用数据类型 ENUM,默认为 SHOWtoBoth)。
将您的 table 更改为:
id 发送者接收者状态时间

我认为使用多个 table 可能是最好的选择 - 每个用户一个 - 以便存档。如果只用一个table,那么加班就真的变大了


我建议的解决方案是将 table 结构编辑为:

id    owner    message    sentby    sentto    created

这样,当用户创建一条消息时,将创建两条记录:发件人的副本和收件人的副本

当UserA发送UserB消息"Good Job"时,查询将是:

sendmessage.php

$you=$_COOKIE['username'];
$recipient="UserB";
$st1="INSERT INTO tbl_msg VALUES ($id,'$you','Good Job','$you','$recipient','$time)";
$st2="INSERT INTO tbl_msg VALUES ($id,'$recipient','Good Job','$you','$recipient','$time)";

inbox.php

$you=$_COOKIE['username'];
$st= "SELECT * FROM mbox WHERE sentto='$you' AND owner='$you' ORDER BY ID DESC LIMIT 10";

outbox.php

$you=$_COOKIE['username'];
$st= "SELECT * FROM mbox WHERE sentby='$you' AND owner='$you' ORDER BY ID DESC LIMIT 10";

delete.php

只需删除 owner='$you' 的那个 从 mbox 中删除 WHERE condition1=value1 AND owner='$you'


基本上,我的解决方法是:当用户发送消息时,我们将两封邮件插入数据库(一份用于收件人的收件箱,另一份用于发件人的发件箱)

当一个用户删除 his/her 消息时,它不会从其他人的 inbox/outbox 中删除,因为每个用户都有自己的消息副本

这可能不是最可靠的解决方案,但它是一个相当实用的解决方案,不需要您对数据库结构进行任何更改。

更改您的删除功能。不要删除数据库中的行,而是做一些检查。弄清楚是发件人还是收件人在进行删除。如果发件人正在删除,请检查是否 sentto == null。如果是,则删除该行。否则,设置 sentby = null。反之亦然。

我假设您 post 用户按下删除键时的消息 ID。还假设您正在使用 PDO。如果这个假设是错误的,请告诉我。

delete.php

$link = new \PDO... // blah blah connection stuff
$id = $_POST['id'];
$messageSELECT = $link->prepare("SELECT `sentby`,`sentto` FROM `mbox` WHERE ID = :id");
$messageSELECT->bindValue(':id',$id,\PDO::PARAM_INT);
$messageSELECT->execute();
$msgInfo = $messageSELECT->fetchAll();

$msgDELETE = null;
if($you == $msgInfo['sentby'] && empty($msgInfo['sentto'])){
  $msgDELETE = $link->prepare("DELETE FROM `mbox` WHERE ID = :id");
} elseif($you == $msgInfo['sentby'] && !empty($msgInfo['sentto'])){
  $msgDELETE = $link->prepare("UPDATE `mbox` SET `sentby` = NULL WHERE ID = :id");
} elseif($you == $msgInfo['sentto'] && empty($msgInfo['sentby'])){
  $msgDELETE = $link->prepare("DELETE FROM `mbox` WHERE ID = :id");
} elseif($you == $msgInfo['sentto'] && !empty($msgInfo['sentby'])){
  $msgDELETE = $link->prepare("UPDATE `mbox` SET `sentto` = NULL WHERE ID = :id");
} else {
  // Shouldn't happen
}
$msgDELETE->bindValue(':id',$id,\PDO::PARAM_INT);
$msgDelete->execute();

根据您当前的数据库结构,不,您不能那样做。让我们从改变您的一些结构开始,以实现您想要的。

1。添加删除的字段

要做的第一件事是添加一个已删除的字段,它是 ENUM(Y, N)。您的 table 的结构将如下所示。

tblMessage(id, message, sentby, sentto, created, deleted)

现在,有了 deleted 字段,它允许接收者删除他们的消息,而发件人仍然保留他们的消息。问题是它不允许发件人从发件箱中删除邮件。

发件箱

SELECT * FROM message WHERE sentby = $you

收件箱

SELECT * FROM message WHERE sentto = $you AND deleted = 'N'

2。做两个tables

为了使其更灵活 (1) 以便发件人可以从发件箱中删除邮件,但接收方仍可以将邮件保留在收件箱中 (2) 以便收件人可以从收件箱中删除邮件,并且发件人仍然在他们的发件箱中收到它。

 tblInbox(id, sendby, message, created, deleted)
 tblOutbox(id, sendto, message, created, deleted)

我认为您可以保留邮件内容当前的 table 结构。与其添加单独的列或删除标志,不如为邮箱单独设置 table。

那么您当前的 mbox table:

id   message    sentby   sentto    created

然后 table user_mailboxes

id   user    mailbox    message_id

您在编写消息时必须总共插入 3 次,一次插入到消息 table,对于 user_mailboxes table 中的每个用户。

因此您的 mbox 数据如下所示:

id   message     sentby    sentto    created 
1    Hi There    UserA     UserB     2015-01-26
2    Hello Back  UserB     UserA     2015-01-26

而 user_mailboxes 数据将如下所示:

id   user        mailbox   message_id
1    UserA       Out       1
2    UserB       In        1
3    UserB       Out       2
4    UserA       In        2

这允许您删除 user_mailboxes table 的个别行。这还允许您同时向多个用户发送消息(每个用户一个新行),并允许您在需要时添加多个邮箱(In、Out、Trash、Important),从而允许将来的附加组件等)。

要为特定邮箱的用户查找邮件,您只需使用连接

SELECT * FROM user_mailboxes LEFT JOIN mbox ON mbox.id = user_mailboxes.message_id WHERE user_mailboxes.user = "$user" AND user_mailboxes.mailbox = "Out";

您在删除时需要一个清理脚本,以确保不存在 user_mailboxes table.

中不存在的孤立邮件

这个任务我也解决了。我认为一个 table 在这种情况下没有用。所以,我建议使用 2 tables:

CREATE TABLE `message` (
  `id`       int(11) NOT NULL AUTO_INCREMENT,
  `subject`  varchar(255) NOT NULL,
  `body`     text NOT NULL,
  `date`     datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `message_user` (
  `id`           int(11) NOT NULL AUTO_INCREMENT,
  `message_id`   int(11) NOT NULL,
  `user_id`      int(11) NOT NULL,
  `interlocutor` int(11) DEFAULT NULL,
  `folder`       enum('inbox','sent') NOT NULL,
  `starmark`     tinyint(1) NOT NULL DEFAULT '0',
  `unread`       tinyint(1) NOT NULL DEFAULT '1',
  `deleted`      enum('none','trash','deleted') NOT NULL DEFAULT 'none',
  PRIMARY KEY (`id`),
  CONSTRAINT `message_user_user_fk_1` FOREIGN KEY (`message_id`)   REFERENCES `message` (`id`) ON UPDATE CASCADE,
  CONSTRAINT `message_user_user_fk_2` FOREIGN KEY (`user_id`)      REFERENCES `user`    (`id`) ON UPDATE CASCADE,
  CONSTRAINT `message_user_user_fk_3` FOREIGN KEY (`interlocutor`) REFERENCES `user`    (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我认为它可以解决您所有的问题,因为消息用户彼此分开

因此,对于一条消息,我们必须像这样创建 3 个插入:

public static function createMessage($subject, $body, $source, $sender_id, $receiver_id)
{
    // save DATA to message table      ($subject, $body, $source)
    // save DATA to message_user table ($message_id, $sender_id, $receiver_id, 'sent')
    // save DATA to message_user table ($message_id, $receiver_id, $sender_id, 'inbox')
}

在这种情况下,我们在 table message_user 中为每个用户创建单独的行。因此,当 user_1 删除此收件箱文件夹中的邮件时,我们将其标记为 'deleted' 并且对第二个用户没有影响。

所以,要获取所有用户消息,我们必须 运行 只是简单 SELECT 像这样:

SELECT *
FROM message m
    JOIN message_user mu
    ON m.id = mu.message_id
WHERE mu.deleted = 'none'
    AND mu.user_id = :user_id
id   message    sentby   sentto    created deteled_from_inbox deteled_from_outbox

我给你的 table 添加了 2 个字段,都将有 YES 和 NO,因为 values.At 首先两个字段都是 NO

$you=$_COOKIE['username'];     
$st= "SELECT* FROM mbox WHERE sentto='$you' AND deteled_from_inbox='NO' ORDER BY ID DESC LIMIT 10";

$you=$_COOKIE['username'];     
$st= "SELECT* FROM mbox WHERE sentto='$you' AND deteled_from_outbox='NO' ORDER BY ID DESC LIMIT 10";

当用户从收件箱中删除数据时,您实际上会用 YES 更新 deteled_from_inbox,因此它不会显示在收件箱中 part.As 我们没有触及 deteled_from_outbox它将显示在发件箱一侧。

只需做一件事,在您现有的 table

中添加两个新字段
  1. is_sender_deleted
  2. is_receiver_deleted

如果有人将其从发件箱中删除,则将 is_sender_deleted 值设置为 1。因此,当您在发件箱中显示数据时,您只需列出所有 is_sender_deleted 字段值为 0 的记录。

同样的情况 ff 有人从收件箱中删除它然后使 is_receiver_deleted 值为 1。因此,当在收件箱中显示数据时,您只需列出所有 is_receiver_deleted 值为 0 的记录。

希望此解决方案对您有所帮助。