За последние 24 часа нас посетили 21649 программистов и 1018 роботов. Сейчас ищут 688 программистов ...

Создание чата между менеджерами и клиентами

Тема в разделе "PHP и базы данных", создана пользователем RazerVG, 21 янв 2015.

  1. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Вы сами заявили, что в диалоге у вас только 1 менеджер и 1 пользователь. Соответсвтенно, чтобы сформировать диалог, нужно вывести сообщения от юзера А к менеджеру Б и наоборот. В чем проблема и зачем вам тут сущность диалоги?
    Если хотите как-то сегментировать беседы между пользователя А и менеджера Б (например после починки снова через неделю протёк унитаз и пользователь снова написал тому же менеджеру и вы хотите отделить 2 этих диалога), используйте timestamp в таблице сообщений. В чем проблема?

    Если вы желаете ускорить извлечение старых диалогов и завести-таки сущность "Диалог на тему протёкшего унитаза", то у вас выходит ещё одна таблица Диалоги и таблица связей: Диалоги-Сообщения или Диалоги-Пользователи-Сообщения.

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

    Опишите как вы будете выводить конкретный диалог в этом варианте.
     
  2. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Ну так это понятно, что только 1 клиент и 1 менеджер в диалоге. А у менеджера может быть несколько диалогов. К примеру одновременно переписываться с двумя клиентами. Вот я и написал, что в случае когда я использую 3 сущности мне непонятно как вывести на страницу диалоги именно открытые диалоги, чтобы менеджер нажав на них увидел переписку.

    То есть примером тут служит контак. Там после открытие "Мои сообщения" выдается список диалогов нажав на них видим сообщения.
    Про связку Диалоги-Пользователи-Сообщения, еще раз пишу, что у меня менеджеры и клиенты в разных таблицах. ПРОБЛЕМА : что по id я должен вывести имя собеседника. Как понять в какую таблицу делать запрос??? Если я делаю поле Отправитель, то туда кидаю id из сессии. И вот тут вся проблема!!! Им может быть как клиент, так и менеджер. Получаеться делая один запрос в случае неудачи надо делать второй в другую таблицу!!! Я так понимаю.
    Дублирование я думаю единственный выход. Только как сделать схему в MySQL WORKBEANCH еще пока не понял.

    Пока в теории схема следующая, при переходе в конкретный диалог, мне нужно по id диалога сделать как-то запрос в две таблицы и потом полученный результат отсортировать по дата/время. Ну это только мысли не знаю такое возможно или нет.
     
  3. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Только вы будете делать запрос не в 2 таблицы, а сразу в 4. (Диалоги, пользователи, менеджеры, сообщения).
    Так вы идентифицируете в вашем ключе кто у вас пользователь клиент или менеджер раз уж по какойто только вам известной причине они у вас в разных таблицах оказались.
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    «Ковыряюсь отверткой в ухе и мне больно. Подскажите как сделать небольно. Ватные палочки не предлагать, я решил, что это должна быть отвертка! Слышал мастера у-шу умеют побеждать боль. Жду вашей помощи, потому что скоро мне надо будет протереть глаз и мне уже страшно.

    Зачем мне отвертка? Объясняю: вот передо мной розетка, в ней болт под крестовую отвертку. Значит мне нужна отвертка. Объясните как лучше всего бороться с болью.»

    p.s. Добавил примеры кода. Тебе не поможет, но кому-нибудь пригодится.
     
  5. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Я же писал, что клиент может общаться только с ему назначенным менеджером и наоборот менеджер с ему назначенными клиентами. Так, что твоя схема не подходит.

    А как сделать идентификацию в ключе ? А если зависти атрибут таблицы "тип клиента" и туда кидать 1 и 2. К примеру 1 менеджер и 2 клиента.

    Добавлено спустя 16 минут 25 секунд:
    А щас еще лучше идея пришла зачем туда вообще нужны idшники клиента и менеджера. Нужно просто добавить атрибут тип сообщения и все и в зависимости от него выводить имя отправителя. Все равно меняя статус диалога к примеру в архиве я не буду его показывать менеджеру. А сообщения остаются привязанными к нему. И как только клиент пишет заново менять этот статус на активный.

    Добавлено спустя 5 минут 7 секунд:
    Только вопрос, а каким запросом мне вывести последнее сообщение из этого диалога. К примеру есть диалог с id=3.

    Запрос .
    Код (Text):
    1. SELECT * FROM messages WHERE id_dialog="3";
     
  6. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    В итоге я остановился на схеме: Клиенты, Менеджеры, Диалоги, Сообщения.

    В сообщениях я не стал кидать idшник, а в зависимости от типа клиента или типа кабинета( они все равно разные), в атрибут тип сообщения кидать значение в зависимости кто пишет. Это выход из ситуации. А при выводе сообщений диалога, в зависимости от него выводить имя.
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    SQL покажи. Твой русский не понять: не стал чего-то кидать, а в зависимости от него (от того чего не стал?) выводишь нечто, откуда непонятно.
     
  8. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Я завожу в таблице сообщения атрибут тип сообщения. Если пишет менеджер кидаю туда 1, если клиент 2. И в зависимости от этого значения вывожу имя из таблице либо менеджеры, либо клиенты.

    Вот только сейчас появилась проблема: как зная id диалога, вывести последнее сообщение.

    Так не выводит:
    Код (Text):
    1. SELECT TOP 1 * FROM messages WHERE id_dialog="1" ORDER BY data DESC
    Добавлено спустя 13 минут 35 секунд:
    Нашел
    Код (Text):
    1. SELECT * FROM messages WHERE id_dialog="1" AND data = (SELECT MAX(data) FROM messages)
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Кхм… я переоценил твои возможности. Писал как человеку, который хотябы основы понимает, но которому нужен совет в проектировании.

    В MySQL выбрать одну запись при заданной сортировке можно вот так:
    Код (Text):
    1. SELECT * FROM моя_таблица ORDER BY моя_сортировка LIMIT 1
    Давай угадаю: на одной странице ты собираешся
    1. получать кучу "последних сообщений" из разных диалогов в цикле
    2. получать кучу "имен автора" из разных диалогов в цикле
    10 диалогов это 21 запрос. Почему бы тебе с твоим эпическим багажем знаний не попытаться вникнуть во взрослые советы?

    Докажи, что я ошибаюсь! Покажи твой SQL: структура таблиц и всё что потребуется для вывода 10 активных диалогов одного Модератора.
     
  10. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Создаем таблицу клиенты

    Код (Text):
    1. CREATE TABLE `clients` (
    2. `id_client` int(11) NOT NULL,
    3.   `code_client` varchar(45) NOT NULL,
    4.   `login` varchar(45) NOT NULL,
    5.   `password` varchar(45) NOT NULL,
    6.   `id_manager` int(11) NOT NULL
    7. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    Создаем таблицу диалоги
    Код (Text):
    1.  
    2. CREATE TABLE `dialogs` (
    3. `id_dialog` int(11) NOT NULL,
    4.   `id_client` int(11) NOT NULL,
    5.   `id_manager` int(11) NOT NULL,
    6.   `status` varchar(45) NOT NULL
    7. ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

    Создаем таблицу менеджеры

    Код (Text):
    1. CREATE TABLE `managers` (
    2. `id_manager` int(11) NOT NULL,
    3.   `first_name` varchar(45) NOT NULL,
    4.   `last_name` varchar(45) NOT NULL,
    5.   `middle_name` varchar(45) NOT NULL,
    6.   `telefon` varchar(45) NOT NULL,
    7.   `email` varchar(45) NOT NULL,
    8.   `password` varchar(45) NOT NULL
    9. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    Создаем таблицу сообщения

    Код (Text):
    1. CREATE TABLE `messages` (
    2. `id_message` int(11) NOT NULL,
    3.   `id_dialog` int(11) NOT NULL,
    4.   `text` varchar(45) NOT NULL,
    5.   `type` varchar(45) NOT NULL,
    6.   `data` datetime NOT NULL
    7. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    Необходимо вывести все диалоги.

    Ввод одного диалога представляет собой: вывод имени клиента и вывод последнего сообщения(текста).

    Ну начнем с малого. С вывода id диалогов менеджера.

    Код (Text):
    1. SELECT id_dialog FROM dialogs WHERE id_manager='1'
    1 бурем из сессии и передаю в функцию

    Усложняем задачу. Вывод еще и логины клиентов

    Код (Text):
    1. SELECT id_dialog, login FROM dialogs, clients WHERE dialogs.id_client = clients.id_client AND dialogs.id_manager='1'
    Кроме как в запросе делать твой запрос подзапросом с передачей ему каждый раз id_dialog выхода я больше не вижу.

    Добавлено спустя 2 минуты 23 секунды:
    Получаеться я пишу функцию для вывода имен клиентов. И внутри нее вставляю еще одну с выводом последнего сообщения.

    Добавлено спустя 1 минуту 50 секунд:
    Потому, что я не могу не зная чему равно id_dialog вывести последнее сообщение. Если в sql, то нужно делать подзапрос.
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Короче недоделал и даже не пытался тестовые данные погонять. Иначе первичный ключ уже появился бы. ;) Скукота.

    Удачи! твори, фантазируй.
     
  12. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Просто я не такой знаток в SQL.

    Смотри вот я раньше делал. К примеру заказ и товары в нем, я выводил товары в этом заказе. То есть как ты пишешь много запросов. Тогда объясни или дай ссылку как делать.

    Код (PHP):
    1. <?php
    2.                     $orders = get_orders_all_in_shop();
    3.  
    4.                     foreach($orders as $order):
    5.                 ?>
    6.  
    7.                 <div class="w-row output_order_cabinet">
    8.                     <div class="w-col w-col-1 output_order_cabinet">
    9.                         <div><?=$order['id_client']?></div>
    10.                     </div>
    11.                     <div class="w-col w-col-2 output_order_cabinet">
    12.                         <div><?=$order['id_order_in_shop']?></div>
    13.                     </div>
    14.                     <div class="w-col w-col-3 output_order_cabinet">
    15.                         <div><?=$order['data_order']?></div>
    16.                     </div>
    17.                     <div class="w-col w-col-3 output_order_cabinet">
    18.                         <div><?=$order['status']?></div>
    19.                     </div>
    20.                     <div class="w-col w-col-3 output_order_cabinet">
    21.                         <div><?=$order['price_order']?></div>
    22.                     </div>
    23.                 </div>
    24.                 <div class="w-row naem_column_item_cabinet">
    25.                     <div class="w-col w-col-4">
    26.                         <div>Название товара</div>
    27.                     </div>
    28.                     <div class="w-col w-col-4">
    29.                         <div>Количество</div>
    30.                     </div>
    31.                     <div class="w-col w-col-4">
    32.                         <div>Цена</div>
    33.                     </div>
    34.                 </div>
    35.  
    36.                     <?php
    37.                         $id_order = $order['id_order_in_shop'];
    38.                         $items_in_orders = get_items_in_orders($id_order);
    39.  
    40.                         foreach($items_in_orders as $item_in_order):
    41.                     ?>
    42.  
    43.                         <div class="w-row item_in_order_cabinet">
    44.                             <div class="w-col w-col-4 item_in_order_column_cabinet">
    45.                                 <div><?=$item_in_order['name']?></div>
    46.                             </div>
    47.                             <div class="w-col w-col-4">
    48.                                 <div class="item_in_order_column_cabinet"><?=$item_in_order['quantity_item_in_order']?></div>
    49.                             </div>
    50.                             <div class="w-col w-col-4">
    51.                                 <div><?=$item_in_order['price']?></div>
    52.                             </div>
    53.                         </div>
    54.  
    55.                     <?
    56.                         endforeach;
    57.                     ?>
    58.                 <?
    59.                     endforeach;
    60.                 ?>
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Я ж дал — на sqlfiddle. Могу добавить еще какие-нибудь поленые запросы на тех же данных, но ты не спрашиваешь.
     
  14. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Посмотрел спасибо. Ну вот на своих данных выведите последнее сообщение из диалога. Без подзапроса. У вас щас выводиться тема диалога. А вот последнее сообщение без подзапроса никак не вытащить.

    Добавлено спустя 5 минут 25 секунд:
    А первичных ключей нет потому, что Workbeanch их вниз кидает.
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    последнЕЕ из диалога? одного диалога??? это чтобы ты его в цикле перебора диалогов крутил? ))) бессмыслица это.
    я тебе дам кое-что интереснее:

    одним запросом последнИЕ сообщенИЯ в каждом диалоге конкретного менеджера:
    вот с подзапросом: http://sqlfiddle.com/#!2/c9e0f8/9
    и то же с доп. полем вместо подзапроса: http://sqlfiddle.com/#!2/0d8115/2 типа оптимизация

    (для фильтра по архивности надо добавить в WHERE … AND d.`is_closed`=0)
     
  16. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Все спасибо!!!. Осталось переделать под свои нужны.
     
  17. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    "переделать под свои нужды" это испортить двумя таблицами пользователей, да? )))
     
  18. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Нет. Просто сделать вывод последнего диалога как у вас, без под запроса.
     
  19. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    ну ёмаё! у меня вывод последнИХ диалогОВ. это блин имеет значение, вообще-то. следи за языком.

    даю еще подсказку по оптимизации: в форумных движках чтобы уменьшить количество join-ов идут на небольшую избыточность: хранят username автора сообщения в самом сообщении. по крайней мере phpbb, punbb и fluxbb делают так.
     
  20. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Описалься последнего сообщения в диалоге.
     
  21. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Он чат пишет, тут вообще, как первичное хранилище, субд н-н не впёрлась.
     
  22. RazerVG

    RazerVG Активный пользователь

    С нами с:
    5 дек 2013
    Сообщения:
    103
    Симпатии:
    0
    Щас кстати еще одно заметил, что у тебя при выводе диалогов они сортируются по дате последнего сообщения. То есть в каком диалоге последнее сообщение тот идет выше, как раз то, что мне нужно. Спасибо.
     
  23. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Не пиши мне в ЛС. Я рад, что дело сдвинулось. Успехов тебе!