php mysql 中的消息系统
Messaging system in php mysql
我在我的网站上创建了一个简单的消息传递系统,新注册用户可以在其中相互发送消息。以下 mysql
语句在我的网站上运行良好,但是
我的问题是- 当 UserA
向 UserB
发送消息时,消息显示给 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,SHOWtoBoth 或 SHOWtoNONE
(使用数据类型 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
中添加两个新字段
- is_sender_deleted
- is_receiver_deleted
如果有人将其从发件箱中删除,则将 is_sender_deleted 值设置为 1。因此,当您在发件箱中显示数据时,您只需列出所有 is_sender_deleted 字段值为 0 的记录。
同样的情况 ff 有人从收件箱中删除它然后使 is_receiver_deleted 值为 1。因此,当在收件箱中显示数据时,您只需列出所有 is_receiver_deleted 值为 0 的记录。
希望此解决方案对您有所帮助。
我在我的网站上创建了一个简单的消息传递系统,新注册用户可以在其中相互发送消息。以下 mysql
语句在我的网站上运行良好,但是
我的问题是- 当 UserA
向 UserB
发送消息时,消息显示给 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,SHOWtoBoth 或 SHOWtoNONE
(使用数据类型 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
中添加两个新字段- is_sender_deleted
- is_receiver_deleted
如果有人将其从发件箱中删除,则将 is_sender_deleted 值设置为 1。因此,当您在发件箱中显示数据时,您只需列出所有 is_sender_deleted 字段值为 0 的记录。
同样的情况 ff 有人从收件箱中删除它然后使 is_receiver_deleted 值为 1。因此,当在收件箱中显示数据时,您只需列出所有 is_receiver_deleted 值为 0 的记录。
希望此解决方案对您有所帮助。