Логика скрипта личных сообщений

С.

Продвинутый новичок
Учиться по большим системам типа phpBB не самая лучшая идея. Там слишком много всяких "бантиков" которые создают шум и скрывают суть. Усилий по выцеплению этой идеи тратится ни чуть не меньше, чем при прихода к ней с нуля (в том числе через расспросы на форуме). Причем последний вариант более полезен, поскольку дает возможность учиться создавать, а не рыться и отбрасывать лишнее, как в первом (надо еще знать, что "лишнее", а что нет).

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

A1x

Новичок
никто и не предлагает учиться по phpBB - только посмотреть как там устроена таблица личных сообщений
ну а вообще волшебных таблеток не существует, все равно придется много всякого кода перелопатить
 

С.

Продвинутый новичок
никто и не предлагает учиться по phpBB
Если бы никто не предлагал, то и пост выше не появился бы. В том и дело, что предложили и именно phpBB.
 

denisOg

Новичок
SiZE
Если не трудно объясните, как работать с таблицой карт в сообщениях?
Как я делал:
Я когда писал скрипт переписки, то в БД добавлял еще два поля, для слежение за удалением. По умолчанию они "1".
Когда удалял один юзер письмо , савил "0".
Естественно, делал проверку, если два нуля удаял полностью из БД.

Это проще карт?
 

aaachilov

Новичок
Чего то меня ббшный код и его структура баз вообще в тупик загнали, пока сделал так что имеется два поля (del_from и del_to) в виде переключателей.

Логика примерно такая - только писать скрипт ещё не начал, пока окончательно не разберусь с логикой


1. Делаю таблицу `лс`
PHP:
- id
- От кого
- Кому
- Собщение
- Дата/время
- Просмотренно или нет (enum '0','1')
- del_from (enum '0','1') мне
- del_to (enum '0','1') от меня

2. Проверка на наличие непрочитанных лс:
PHP:
SELECT COUNT(*) FROM `лс` WHERE кому = мне and enum = 0
3. Скрипт обработки и вывода входящих лс
PHP:
SELECT * FROM `лс` WHERE кому = мне and del_from = 0 ORDER BY `дата/время` and `id` DESC
PHP:
$marker = (to == 0 ? 2 : 3); // значение для переключателя запроса к базе на удаление

4. Скрипт обработки и вывода исходящих лс
PHP:
SELECT * FROM `лс` WHERE от кого = от меня and del_to = 0 ORDER BY `дата/время` and `id` DESC
PHP:
$marker = (from == 0 ? 1 : 3); // значение для переключателя запроса к базе на удаление
5. Скрипт обработки и вывода переписки
PHP:
SELECT * FROM `лс` WHERE (от кого = от меня and del_to = 0) or (кому = мне and del_rfom = 0) ORDER BY `дата/время` and `id` DESC
PHP:
if (Кому == мне) {$marker = (to == 0 ? 2 : 3);} else {$marker = (from == 0 ? 1 : 3);} // значение для переключателя запроса к базе на удаление

6. Скрипт обработки и удаления сообщений
PHP:
switch ($marker) {
case 1: UPDATE  to ; break;
case 2: UPDATE  from ; break;
case 3: DELETE   ; break;
}
Вот только теперь думаю как лучше передать значение маркера в скрипт удаления
 

aaachilov

Новичок
Ещё раз приветствую!
Люди добрые - выручайте - помогите с логикой и структурой баз данных.
То что описано выше решено, но встал другой вопрос.

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

Проблемма в том что никак не могу решить вопрос с тем, как мне вывести список пользователей с которыми ведётся переписка. (Как пример интерфейс "Одноклассников").
На данном этапе имеется две таблицы.
Переписки (dialog):
PHP:
id | from_user | to_user | datetime
Собщения (message):
PHP:
id | dialog_id | user | message | date |  from_del | to_del | view
Логика примерно такая:
1) Один из пользователей начинает диалог, например пользователь user_1 начал диалог с пользователем user_2.
2) Проверяем нет ли у нас уже диалога этой пары пользователей (1 запрос к базе), если нет то заносим в таблицу `dialog` следующую запись:
PHP:
id | from_user | to_user |  date
----------------------------------------
1  |  user_1   | user_2  | 1.01.01 10:00
если есть диалог между данными пользователями перезаписываем дату для данного диалога(2 запрос к базе).
3) Выводим список всех диалогов в которых учавствует пользователь user_1, сортируем по дате, вверху окажется последний (3 запрос к базе).
4) Выводим список сообщений диалога пользователей который первый в списке диалогов (4 запрос к базе).
Дальше уже пишем сообщения в таблицу `message` или проводим иные манипуляции.
Не буду писать про удаление сообщений и т.д.

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

Надеюсь подробно объяснил - не буду выкладывать код, думаю и это лень кому будет обдумывать.
У кого не спрашивал все тычут на карты пользователей, хоть бы при этом ссылочку какую дали что это такое и с чем это едят.
Заранее премного благодарен.
 

Фанат

oncle terrible
Команда форума
SELECT u.* FROM ls, users u WHERE ls.to_user=u.id AND from_user=текущий GROUP BY to_user ORDER BY date?

а зачем нужна таблица dialog?
 

aaachilov

Новичок
Фанат
Спасибо за ответ, я много варианто в перепробывал - но у меня проблемма именно в том что не могу верно структуру базы данных выстроить.
Из вышего запроса к базе ещё больше запутался в плане структуры таблицы данных)))
Я сейчас решил вопрос с вариантом который представил выше - но по уродски - просто из результата выборки диалогов мне приходит от кого и кому, например Маша-Ваня , Маша-Женя Саша - Маша я просто удалил preg_replace логин текущего пользователя из результата и получил список.
на счёт таблицы dialog могу следующее сказать. Я подумал что так будет практичнее - во первых сообщений может быть тысячи а диалогов всего 100 например. подумал что быстрее и менее затратно отработает запрос на вывод диалогов если будет отдельная таблица, да и в таблице с сообщениями убралось одно поле и не нужно каждый раз писать от кого кому, таким образом хранить одно и тоже много раз, а только имя пользователя который написал сообщение, а выведутся они в порядке даты добавления.
Но после Вашего вопроса даже растерялся)))
Когда только начал изучать PHP и MYSQL то думал что сложность в изучени языка и написании скриптов, а теперь оказывается что самое сложное выстроить верную логику и структуру баз данных, а написать скрипт, когда видешь поэтапно его работу сложностей не представляет.
 

Фанат

oncle terrible
Команда форума
Не понимаю, зачем в запросе запрашивать от кого, потом записывать это имя в какую-то строку(?) и потом удалять из неё прег реплейсом.
Не проще сразу НЕ запрашивать имя текущего пользователя?

В моем запросе, косяк, кстати. он не покажет тех, кто пользователю написал, но остался без ответа.
 

aaachilov

Новичок
Ну просто когда создаётся диалог я не понимаю как мне разделить пользователей так чтоб просто сказать, дай мне все диалоги с моим участием и вывести имена тех с кем я веду диалог. В моём случае получилосьтак, что я говорю - дай мне все диалоги где я: либо инициатор, либо второй участник. И как при этом выбрать и вывести имена тех с кем я начал диалог.
Например имея таблицу с диалогами следующего содержания.
PHP:
id | from_user | to_user |  date
----------------------------------------
1  |  user_1   | user_2  | 1.01.01 10:00
2  |  user_3   | user_1  | 1.01.01 12:00
3  |  user_2   | user_4  | 1.01.01 14:00
4  |  user_5   | user_1  | 1.01.01 16:00
и таким запросом
PHP:
$db->query("SELECT `id`, `from_user`, `to_user`
            FROM `user_dialog` 
            WHERE (`from_user` = '".$user_1."') or (`to_user` = '".$user_1."') 
            ORDER BY `date` 
            DESC");
я получу массив
PHP:
id | from_user | to_user 
--------------------------
4  |  user_5   | user_1  
2  |  user_3   | user_1  
1  |  user_1   | user_2
Как выделить имена пользователей с которыми я веду переписку?
Я сделал так
PHP:
$user_name = preg_replace("/$user_1/","",$from_user.$to_user);
Опять же в таблице с диалогами поля from и to это условно - по сути это просто пользователь 1 и пользователь 2
 

Sufir

Я не волшебник, я только учусь
Вот тут посмотрите. Я сделал так: у меня одна таблица для всего что связано с сообщениями. Одним запросом получаем список "переписок" с текстом последнего сообщения:

http://phpclub.ru/talk/threads/Здравствуйте-есть-2-таблицы-Пользователи-users-Переписки-conver-необходимо-вывести-группирован.69890/#post-624802

Как пример реализации, не более. Единственное - у меня есть разделение на входящие/исходящие, но тут небольшая правка запроса...
 

aaachilov

Новичок
Sufir
Спасибо за ответ, но я сейчас забил в базу 50 000 записей и потестил при различных вариантах.
В некоторый ситуациях вариант с двумя таблицами работает почти в 3 раза быстрее.
Сейчас ещё попробую пол ляма записей вбить и потестить
 

Sufir

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

SiZE

Новичок
SiZE
Если не трудно объясните, как работать с таблицой карт в сообщениях?
Как я делал:
Я когда писал скрипт переписки, то в БД добавлял еще два поля, для слежение за удалением. По умолчанию они "1".
Когда удалял один юзер письмо , савил "0".
Естественно, делал проверку, если два нуля удаял полностью из БД.

Это проще карт?
В зависимости от целей реализация и подход могут быть разные. Твое решение проще того, что я предлагал, но не подходит когда в переписке участвует более 2-х лиц. Слово карта — это условное название таблицы, которая хранит информацию о пользователях участвующих в переписке.
 

SiZE

Новичок
2) Проверяем нет ли у нас уже диалога этой пары пользователей (1 запрос к базе), если нет то заносим в таблицу `dialog` следующую запись
...
если есть диалог между данными пользователями перезаписываем дату для данного диалога(2 запрос к базе).
Можно заменить на
INSERT ... ON DUPLICATE KEY UPDATE date=NOW() и конечно добавить уникальный ключ для from_user и to_user.
 

SiZE

Новичок
Как выделить имена пользователей с которыми я веду переписку?
PHP:
$db->query("SELECT `id`, `from_user`, `to_user`, CASE WHEN `from_user` = '".$user_1."' THEN TRUE ELSE FALSE END as is_starter
            FROM `user_dialog` 
            WHERE (`from_user` = '".$user_1."') or (`to_user` = '".$user_1."') 
            ORDER BY `date` 
            DESC");
// ...

if ( $is_starter ) {
 // делаю чо хочу
}
 
Сверху