Организация внутренних сообщений в системе (аналог почты)

Руслан

Новичок
Организация внутренних сообщений в системе (аналог почты)

Вопрос возможно несколько теоретический, но возник он как это часто бывает из практической необходимости.
Итак задача, реализовать в системе (по сути большой непубличный сайт) внутренню почту. То есть переписка между пользователями сайта.
Делаю через одну таблицу (не знаю верно ли решил), структура кратко следующая.

id | датавремя | от | кому | тема | текст | вложение | статус |

Когда делаем вывод исходящих - всё просто. Проверяем соотвествие id пользователя в поле "от" и сессии и вытаскиваем на свет божий тему и всё пр. А вот как со входящими? Есть же возможность отправки многим пользователям (причём это предполагается часто использовать). В поле "кому" при отправке многим пользователям, их id записываются через запятую-пробел, т.е. так "1, 3, 6, 43, 53". Понятно, что проверять на точное соответсвие id в сессии и значения поля "кому" бессмыслено. Мне сразу подумалось, что можно попробовать делать приблизительное соответствие, и по найденым строкам потом разбивать эти id в массив через explode b проверять уже на точное соответствие с id пользователя в сессии.. Но выглядит это, мягко говоря, вычурно. Внутренний голос какбэ намекает мне, что возможно я организовал базу неверно под эту задачу.
Может кто сталкивался с подобным, какие решения реализуют стандартно и в каких случаях?
 
Внутренний голос какбэ намекает мне, что возможно я организовал базу неверно под эту задачу.
внутренний голос какбэ прав. )
Тебе нужна таблица связей один к многим id сообщения - id получателей.
 
Автор оригинала: флоппик
внутренний голос какбэ прав. )
Тебе нужна таблица связей один к многим id сообщения - id получателей.
Что-то я чего-то не могу понять. А что тогда будет в поле "кому"? Как получится один ко многим? Вы имеете ввиду, что будет таблицв
/ id / id пользователя / имя пользователя / id сообщения ?

Но тогда получится
/ 1 / 12 / Иванов / 12,123,21,

или
/ 1 / 12 /Иванов / 12
/ 2 / 12 /Иванов / 123
/ 3 / 12 /Иванов / 21

Или не так? Я просто сейчас материалы читаю, не до конца пока вижу как это приложить к моей задаче.
 
id | id получателя | id отправителя | … текст и прочая фигня
 
Руслан, а ты если получателей много, создавай несколько записенй отличающихся id получателя. потому что статусы тоже нужны для каждого получателя, возможность удалять сообщения и т.п.

п.с. прочитай про первую нормальную форму базы данных
 
dimagolov, ну в принципе ведь можно статусы и удаление сделать в той таблице, где связь многих ко многим (т.е. помечать удаленным). Если изменять сообщение после отправки не планируется, то думаю, что так лучше.
ИМХО, место хотя бы можно сэкономить будет.
 
Ну и получится в итоге таблица от кого к кому и всякими флагами и связанная таблица с текстом. Но на практике, в общем, с этим хозяйством неудобно работать - очень уж усложняется логика приложения. Так что я бы советовал одну таблицу и каждое письмо - одна запись. Если, конечно, специфика такая, что там килобайты текста будут рассылкаться пользователям, то можно и вынести в отдельную таблицу.
 
Я вчера перед сном лежал думал и вот чего надумал.

первая таблица
id, дата, от, тема, текст, вложение

вторая таблица
id сообщения, кому, статус

таким образом получится что запись с текстом будет одна, а записей со статусом и кому будет столько сколько адресатов. Насколько будет сложной логика при такой структуре, какие могут быть сложности?
 
Очевидно, что просто запросы будут несколько сложнее и надо будет через какое-то время удалять записи из первой таблицы, на которую больше нет ссылок.
 
Ну получится, что при выводе входящих вместо одного запроса к одной таблице будет два запроса к двум таблицам. Т.е первый запрос - вывести все из таблицы 2 (id сообщения, дата, кому, статус) где кому = id пользователя в сессии и статус не равен "удален" сортируюя по "дата" в обратном порядке. Потом при разбивке ответа в масив на каждый оборот будет делаться запрос к таблице 1 (id, от, тема, текст, вложение) где id = резульату id сообщения от первого первого запроса.

Кстати есть смысл во второй таблице делать дополнительное инкрементное поле id?

P.S.
А можно перенести ещё и "тему" в таблицу 2. В этом случае при выводе входящих, как списка, к первой таблице вобще обращаться не придётся. Но конечно появится избыточность информации по "тема". Хотя тема обычно небольшая, а бывает что её вобще не пишут. Возможно так и сделаю.
 
Кстати есть смысл во второй таблице делать дополнительное инкрементное поле id?
Теоретически - нет, достаточно ПК по (id письма, id получателя), на практике иногда ссылатся на суррогатный ключ в запросах и прочих расчетах чуть проще.
 
И наверно в заключение такой вопрос. А что со связями? Я читал, что устанавливаются связи. То есть вроде как база производит синхронизацию по определенным внешним ключам. Здесь это востребовано? И если да, то как это будет работать? Просто, как я посмотрю, имея две таблицы с такой организацией, смысла в дополнительных связях не видно. Или я что-то упускаю?
 
Просто, как я посмотрю, имея две таблицы с такой организацией, смысла в дополнительных связях не видно.
Ты прав. Максимум, что ты можешь сделать с помощью FK - избежать отправки сообщений несуществующим пользователям. Грубо говоря, FK нужны для сохранения целостности БД, а у тебя целостность нарушить сложно, да и целостность этих данных скорее всего некритична.
 
Всё. Всем спасибо. Возможно эта тема пригодится не только мне, но идругим новичкам форума.

-~{}~ 04.10.10 16:34:

А на практике выходит, что тема себя не исчерпала.
А имено:
если поле "от" оставить там где полный текст сообщения, то возникают проблемы с сортировкой по "дате", которая находится в таблице с получателями.. вобщем похоже что поле "от" нужно переносить в ту же таблицу где и получатели. А в первой таблице остаётся только id и текст сообщения.
 
если поле "от" оставить там где полный текст сообщения, то возникают проблемы с сортировкой по "дате", которая находится в таблице с получателями..
при чем здесь поле from и сортировка по дате? да и какая проблема сортировки по дате, если все равно запрос идет сразу к двум таблицам? или ради того, чтобы запрос списка сообщений производился только к одной таблице? если да, то придется смириться с дублированием части данных.
 
Автор оригинала: dimagolov
при чем здесь поле from и сортировка по дате?
Получается так. Когда открываю список входящих - делаю первый запрос к таблице "Б" имеющей "дата" и "кому" где кому = айди юзера в сесси и статус не = "корзина" с сортировкой по дате , при построчном выводе делаю запрос к таблице "А" с текстом сообщения, чтобы вытащить отправителя для этого письма.
А когда открываю исходящие, то сначала приходится обращаться к таблице "А" с текстом сообщения, потому что поле "from" в ней. Получается, что мы вытаскиваем все id из этой таблицы без сортировки. После того как вытащили, делаем перебором запросы к таблице "Б" подставляя те id, которые вытащили, на соответствие с mes_id (id сообщения в таблице "Б") предположим с сортировкой по дате. Но сортировка то будет уже не верная. Потому что запросы к таблице "Б" разбились, и происходят уже для каждого отдельного сообщения, а не для всех сообщений по полю "from". Так ведь? Есть конечно вариант занести результат от таблицы "А" в масив и сделать запрос к "Б" на подобие select .. where `mes_id`='результат1' OR `mes_id`='результат2' OR `mes_id`='результат3' order by datetime, но это как-то громоздко учитывая, что таких результатов со временем могут быть тысячи. Можно попробовать совмещать запросы к базам аля union, можно после того как разбитые запросы к "Б" отдадут результат погонять их в массиве и гонять их методом пузырька =). Но это уже тоже не дело.
Я может быть что-то упустил или даже не знаю. Поэтому вы объясните толком, что вы имеете ввиду, может быть действительно есть какие-нибудь варианты (я даже опять думал о том, что могут дать связи), при которых держать, а значит дублировать поле from в табилце "Б" для каждого получателя не потребуется.
 
ууу. Быстро, учить SQL, читать про JOIN.
Про FK знает, а основы синтаксиса SQL - нет )
 
Автор оригинала: флоппик
ууу. Быстро, учить SQL, читать про JOIN.
Про FK знает, а основы синтаксиса SQL - нет )
Да, верно. Join'ом ещё не пользовался. Хм.. Почитал. Тема, понятное дело, исчерпана.
 
Сверху