Я создал простую систему обмена сообщениями на своем веб-сайте, где новые зарегистрированные пользователи могут отправлять сообщения друг другу. следующий оператор mysql
хорошо работает на моем сайте, но моя проблема заключается в том, что когда UserA
отправляет сообщение пользователю UserB
, сообщение отображается в UserB
в его UserB
Входящие», и сообщение отображается в UserA
в его UserB
Исходящие», теперь, если по некоторым причинам 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";
Я думаю, вы можете сохранить свою текущую структуру таблицы для содержимого сообщения. Вместо добавления отдельных столбцов или удаленных флагов вам будет лучше иметь отдельную таблицу для почтовых ящиков.
Итак, ваша текущая таблица mbox:
id message sentby sentto created
Затем другая таблица для user_mailboxes
id user mailbox message_id
Вам нужно будет сделать три полных вставки при записи сообщения, в таблицу сообщений, для каждого пользователя в таблице user_mailboxes.
Таким образом, ваши данные 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. Это также позволит использовать будущие надстройки, позволяя одновременно отправлять сообщения нескольким пользователям (новая строка для каждого пользователя) и позволять вам добавлять более одного почтового ящика (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.
Просто добавьте два новых поля в существующую таблицу
Если кто-то удалит его из outbox, сделайте is_sender_deleted значение равным 1. Поэтому, когда вы показываете данные в outbox, вы просто перечислите все записи, у которых значение is_sender_deleted 0.
В той же ситуации, если кто-то удалит ее из папки «Входящие», а затем сделает is_receiver_deleted значение 1. Итак, когда вы показываете данные в папке «Входящие», вы просто перечисляете все записи, у которых значение is_receiver_deleted равно 0.
Надейтесь, что это решение поможет вам.
Я также решил эту задачу. Я думаю, что одна таблица в этом случае не полезна. Итак, я предлагаю использовать 2 таблицы:
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') }
В этом случае для каждого пользователя мы создаем отдельную строку в таблице message_user
. Поэтому, когда user_1 удаляет сообщение в этой папке «Входящие», мы отмечаем его как «удаленный» и не влияем на второго пользователя.
Итак, чтобы получить все пользовательские сообщения, мы должны запускать только простой 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
Вы можете добавить столбец типа «статус» в таблицу mbox,
Затем; если 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";
Удачи.
Вместо того, чтобы удалять сообщения из базы данных, используйте статус этого конкретного сообщения
Как SHOWtoSender , SHOWtoReciver , SHOWtoBoth или SHOWtoNONE
( используйте тип данных ENUM и по умолчанию SHOWtoBoth ).
Внесите изменения в таблицу как:
время ожидания отправителя идентификатора отправителя
Добавьте столбец, например has_mail
который имеет значение по умолчанию, например AB
что означает, что у пользователей есть почта. Теперь, если кто-либо удалил из своего окна ввода / вывода, то конкретный 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";
Теперь вы можете удалить сообщение из db, когда оба поля пустые:
DELETE FROM mbox WHERE LENGTH(has_mail) < 1
id message sentby sentto created deteled_from_inbox deteled_from_outbox
К вашей таблице я добавил 2 поля, оба будут иметь ДА и НЕТ как значения. Сначала оба поля будут 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";
Когда пользователь удаляет данные из папки «Входящие», вы фактически обновляете deteled_from_inbox
с помощью YES
, поэтому он не будет отображаться в папке «Входящие». Поскольку мы не deteled_from_outbox
он будет отображаться в стороне исходящих сообщений.
Я думаю, что лучше всего использовать несколько таблиц – по одному для каждого пользователя – для их архивации. Если вы используете только одну таблицу, то сверхурочное время станет действительно большим.
Решение, которое я предлагаю, заключается в том, что вы редактируете свою структуру таблицы в:
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
просто удалите тот, который владелец = '$ you' DELETE FROM mbox WHERE condition1 = value1 AND owner = '$ you'
В основном, мое обходное решение выглядит так: когда пользователь отправляет сообщение, мы вставляем два сообщения в базу данных (одна копия для входящих почтовых ящиков получателя и другая копия для исходящих отправителей)
Когда пользователь удалил свое сообщение, он не будет удален из папки «Входящие» / «Исходящие» другого, поскольку у каждого пользователя есть своя копия сообщения
Это может быть не самое надежное решение, но оно довольно функциональное и не требует внесения каких-либо изменений в структуру вашего БД.
Измените функцию удаления. Вместо удаления строки в базе данных выполните несколько проверок. Выясните, является ли отправитель или получатель удалением. Если отправитель удаляется, проверьте, если sentto == null
. Если это так, удалите строку. Else, set sentby = null
. И наоборот.
Я буду считать, что вы отправляете идентификатор сообщения, когда пользователь нажимает на удаление. Также предполагается, что вы используете 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();
С вашей текущей структурой базы данных нет, вы не можете этого сделать. Давайте начнем с внесения изменений в некоторые из ваших структур для достижения желаемого.
Первое, что нужно сделать, это добавить одно удаленное поле, где оно равно ENUM (Y, N). Структура таблицы будет выглядеть так.
tblMessage(id, message, sentby, sentto, created, deleted)
Теперь, с удаленным полем, он позволяет получателю удалять свое сообщение, а отправитель по-прежнему сохраняет свое сообщение. Проблема заключается в том, что он не позволяет отправителю удалять свое сообщение из своей папки «Исходящие».
Исходящие
SELECT * FROM message WHERE sentby = $you
входящие
SELECT * FROM message WHERE sentto = $you AND deleted = 'N'
Чтобы сделать его более гибким (1), чтобы отправитель мог удалить сообщение из своего исходящего, но получение по-прежнему может сохранить сообщение в своем почтовом ящике (2), чтобы получатель мог удалить сообщение из своего почтового ящика, а отправитель все еще получил его в их исходниках.
tblInbox(id, sendby, message, created, deleted) tblOutbox(id, sendto, message, created, deleted)
Если вы не хотите потерять какие-либо данные из своей базы данных и не хотите изменять свою базу данных, но все же хотите, чтобы ваши пользователи имели возможность «удалять» свои сообщения, просто добавьте строку перед «sendby» или поле «sentto». Это применяется, если sentBy и sentTo имеют строковые значения
For example: UserA sents a message to UserB. in your table you have: id message sentby sentto created msgid msg UserA UserB date
В вашем действии «удалить», если это сделано UserB, добавьте строку «DeleteD —» перед UserB в поле db, отправленное. Итак, теперь ваш db выглядит так:
id message sentby sentto created msgid msg UserA DeleteD---UserB date
В вашем php-коде создайте некоторые функции, которые проверили бы, существует ли строка «DeleteD —» в поля sentBy или sentTo, прежде чем делать что-либо еще:
function checkForDeleted($str) { if (strpos($str,'DeleteD---') !== false) { return true; } } function getUserIfDeleteD($str) { $user=array(); if(checkForDeleted($str)===true) { $arr=explode("---",$str); $user=$arr[1]; return $user; } }
Таким образом, вы «сохраняете» информацию в своей таблице базы данных, чтобы быть доступной для обоих пользователей, убедившись, что если UserB удалит сообщение, отправленное UserA, тогда UserA все равно сможет видеть в своем исходном поле пользователя, которому он отправил массаж. Если оба пользователя удаляют одно и то же сообщение позже, вы можете полностью удалить из базы данных.
В случае sentBy и sentTo имеют значения userid (целые числа), тогда я предлагаю добавить только одно поле в конце таблицы
id message sentby sentto created deleted_message_flag msgid msg UserA_id UserB_id date 00 ALTER TABLE `messages` ADD COLUMN `deleted_message_flag` bit(2) NOT NULL AFTER `created`;
как работает вышеуказанное поле? В качестве двоичного индикатора для отправления и отправления относительно того, кто удалил сообщение из своего почтового ящика. Если сообщение не удаляется, тогда значение равно 0, если оно удалено, тогда значение равно 1. Первый бит для sentBy, а второй бит – для sentTo. Таким образом, вы храните меньше данных и создаете только одно поле в текущей таблице. Как вы анализируете 2 бита?
deleted_message_flag deleted_from_sentBy deleted_from_sentTo 00 0 0 01 0 1 10 1 0 11 1 1