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

Руслан

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

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

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

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

флоппик

promotor fidei
Команда форума
Партнер клуба
Внутренний голос какбэ намекает мне, что возможно я организовал базу неверно под эту задачу.
внутренний голос какбэ прав. )
Тебе нужна таблица связей один к многим id сообщения - id получателей.
 

Руслан

Новичок
Автор оригинала: флоппик
внутренний голос какбэ прав. )
Тебе нужна таблица связей один к многим id сообщения - id получателей.
Что-то я чего-то не могу понять. А что тогда будет в поле "кому"? Как получится один ко многим? Вы имеете ввиду, что будет таблицв
/ id / id пользователя / имя пользователя / id сообщения ?

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

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

Или не так? Я просто сейчас материалы читаю, не до конца пока вижу как это приложить к моей задаче.
 

baev

‹°°¬•
Команда форума
id | id получателя | id отправителя | … текст и прочая фигня
 

dimagolov

Новичок
Руслан, а ты если получателей много, создавай несколько записенй отличающихся id получателя. потому что статусы тоже нужны для каждого получателя, возможность удалять сообщения и т.п.

п.с. прочитай про первую нормальную форму базы данных
 

FB3

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

MiksIr

miksir@home:~$
Ну и получится в итоге таблица от кого к кому и всякими флагами и связанная таблица с текстом. Но на практике, в общем, с этим хозяйством неудобно работать - очень уж усложняется логика приложения. Так что я бы советовал одну таблицу и каждое письмо - одна запись. Если, конечно, специфика такая, что там килобайты текста будут рассылкаться пользователям, то можно и вынести в отдельную таблицу.
 

Руслан

Новичок
Я вчера перед сном лежал думал и вот чего надумал.

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

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

таким образом получится что запись с текстом будет одна, а записей со статусом и кому будет столько сколько адресатов. Насколько будет сложной логика при такой структуре, какие могут быть сложности?
 

Вурдалак

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

Руслан

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

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

P.S.
А можно перенести ещё и "тему" в таблицу 2. В этом случае при выводе входящих, как списка, к первой таблице вобще обращаться не придётся. Но конечно появится избыточность информации по "тема". Хотя тема обычно небольшая, а бывает что её вобще не пишут. Возможно так и сделаю.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Кстати есть смысл во второй таблице делать дополнительное инкрементное поле id?
Теоретически - нет, достаточно ПК по (id письма, id получателя), на практике иногда ссылатся на суррогатный ключ в запросах и прочих расчетах чуть проще.
 

Руслан

Новичок
И наверно в заключение такой вопрос. А что со связями? Я читал, что устанавливаются связи. То есть вроде как база производит синхронизацию по определенным внешним ключам. Здесь это востребовано? И если да, то как это будет работать? Просто, как я посмотрю, имея две таблицы с такой организацией, смысла в дополнительных связях не видно. Или я что-то упускаю?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Просто, как я посмотрю, имея две таблицы с такой организацией, смысла в дополнительных связях не видно.
Ты прав. Максимум, что ты можешь сделать с помощью FK - избежать отправки сообщений несуществующим пользователям. Грубо говоря, FK нужны для сохранения целостности БД, а у тебя целостность нарушить сложно, да и целостность этих данных скорее всего некритична.
 

Руслан

Новичок
Всё. Всем спасибо. Возможно эта тема пригодится не только мне, но идругим новичкам форума.

-~{}~ 04.10.10 16:34:

А на практике выходит, что тема себя не исчерпала.
А имено:
если поле "от" оставить там где полный текст сообщения, то возникают проблемы с сортировкой по "дате", которая находится в таблице с получателями.. вобщем похоже что поле "от" нужно переносить в ту же таблицу где и получатели. А в первой таблице остаётся только id и текст сообщения.
 

dimagolov

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

флоппик

promotor fidei
Команда форума
Партнер клуба
ууу. Быстро, учить SQL, читать про JOIN.
Про FK знает, а основы синтаксиса SQL - нет )
 

Руслан

Новичок
Автор оригинала: флоппик
ууу. Быстро, учить SQL, читать про JOIN.
Про FK знает, а основы синтаксиса SQL - нет )
Да, верно. Join'ом ещё не пользовался. Хм.. Почитал. Тема, понятное дело, исчерпана.
 
Сверху