Система обмена сообщениями в 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";

Ответ 1

Я думаю, вы можете сохранить свою текущую структуру таблицы для содержимого сообщения. Вместо добавления отдельных столбцов или удаленных флагов вам будет лучше иметь отдельную таблицу для почтовых ящиков.

Итак, ваша текущая таблица 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";

Вам потребуется очистить script при удалении, чтобы убедиться, что в таблице user_mailboxes нет сиротских сообщений, которые не существуют.

Ответ 2

Просто добавьте два новых поля в существующую таблицу

  • is_sender_deleted
  • is_receiver_deleted

Если кто-то удалит его из outbox, сделайте значение is_sender_deleted равным 1. Поэтому, когда вы показываете данные в outbox, вы просто перечисляете все записи, у которых значение is_sender_deleted 0.

В той же ситуации, если кто-то удалит ее из папки "Входящие", а затем сделает значение is_receiver_deleted 1. Итак, когда вы показываете данные в папке "Входящие", вы просто перечисляете все записи, чье значение is_receiver_deleted равно 0.

Надеемся, что это решение поможет вам.

Ответ 3

Я также решил эту задачу. Я думаю, что одна таблица в этом случае не полезна. Итак, я предлагаю использовать 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

Ответ 4

Вы можете добавить столбец типа "статус" в таблицу 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";

Удачи.

Ответ 5

Добавьте столбец типа 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 

Ответ 6

Вместо удаления сообщений из базы данных используйте статус этого конкретного сообщения
SHOWtoSender, SHOWtoReciver, SHOWtoBoth или SHOWtoNONE
(используйте тип данных ENUM и по умолчанию SHOWtoBoth).
Внесите изменения в таблицу как:
время ожидания отправителя идентификатора отправителя

Ответ 7

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, он будет отображаться в стороне исходящих сообщений.

Ответ 8

Я думаю, что лучше всего использовать несколько таблиц - по одному для каждого пользователя - для их архивации. Если вы используете только одну таблицу, то сверхурочное время станет действительно большим.


Решение, которое я предлагаю, заключается в том, что вы редактируете свою структуру таблицы в:

id    owner    message    sentby    sentto    created

Таким образом, когда пользователь создает сообщение, будут созданы две записи: копия отправителя и копия рецензента

Когда UserA отправляет UserB сообщение "Хорошее задание", запрос будет выглядеть следующим образом:

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'


В принципе, мое обходное решение похоже: когда пользователь отправляет сообщение, мы вставляем два сообщения в базу данных (одна копия для входящих почтовых ящиков получателей и другая копия для исходящих отправителей)

Когда пользователь удалил свое сообщение, он не будет удален из другого почтового ящика/исходящей почты, потому что у каждого пользователя есть своя копия сообщения

Ответ 9

Это может быть не самое надежное решение, но оно довольно функциональное и не требует внесения каких-либо изменений в структуру вашего БД.

Измените функцию удаления. Вместо удаления строки в базе данных выполните несколько проверок. Выясните, является ли отправитель или получатель удалением. Если отправитель удаляется, проверьте, есть ли sentto == null. Если это так, удалите строку. Else, установите 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();

Ответ 10

С вашей текущей структурой базы данных нет, вы не можете этого сделать. Начните с внесения изменений в некоторые из ваших структур, чтобы достичь того, чего вы хотите.

1. Добавить удаленное поле

Первое, что нужно сделать, это добавить одно удаленное поле, где оно равно 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'

2. Сделайте две таблицы

Чтобы сделать его более гибким (1), чтобы отправитель мог удалить сообщение из своего исходящего, но получение по-прежнему может сохранить сообщение в своем почтовом ящике (2), чтобы получатель мог удалить сообщение из своего почтового ящика, а отправитель все еще получил его в исходной папке.

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

Ответ 11

Если вы не хотите потерять какие-либо данные из своей базы данных и не хотите изменять свою базу данных, но все же хотите, чтобы ваши пользователи имели возможность "удалять", их сообщения, просто добавьте строку в перед полем "sentby" или "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

В вашем действии "delete", если это сделано 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