С помощью php и foreach вывести списком все уникальные чаты, а в которых есть непрочитанные сообщения - добавить иконку уведомления
пробовал так, но выводит все уникальные значения, т.е. 2 варианта для конкретного чата с уведомлением($icon) и без :
if( $see == 0 ) { $icon = '<div class="icon"></div>'; } else { $icon = ''; }
$arr[] = '<div>'.$icon.'</div>';
$el = array_unique($arr);
foreach($el as $el) { echo($el); }
вот думаю как с помощью foreach оставить для конкретного чата из 2х значений (с уведомлением и без) только одно - с уведомлением (оно же в массиве есть, а выборку не могу придумать как сделать)
сори, но голова уже не варит - вот первый мой вопрос на стаке, не кидайтесь камням :)
вот весь код (используется Redbeanphp для работы с базой):
echo('<div class="message-list">');
$message_list = R::findAll('messages', 'ORDER BY time ASC');
foreach ($message_list as $message_list) {
if( in_array($message_list->whom_id, $_SESSION['company']) && $message_list->whom_type == 'c' || in_array($message_list->from_id, $_SESSION['company']) && $message_list->from_type == 'd' ){
if( ( !in_array($message_list->from_id, $_SESSION['company']) && $message_list->from_type == 'c' ) || $message_list->from_type == 'u' ){
if( $message_list->from_type == 'u' ) {
$m_user_list = R::find('users', 'id= ?', [$message_list->from_id]);
foreach ($m_user_list as $m_user_list) { $m_from_list = $m_user_list->name .' '. $m_user_list->surname; $m_img_list_from = $m_user_list->avatar; }
} else {
$m_user_list = R::find('companys', 'id= ?', [$message_list->from_id]);
foreach ($m_user_list as $m_user_list) { $m_from_list = $m_user_list->name; $m_img_list_from = $m_user_list->logo; }
}
if( $message_list->whom_type == 'u' ) {
$m_whom_list = R::find('users', 'id= ?', [$message_list->whom_id]);
foreach ($m_whom_list as $m_whom_list) { $m_img_list_whom = $m_whom_list->avatar; }
} else {
$m_whom_list = R::find('companys', 'id= ?', [$message_list->whom_id]);
foreach ($m_whom_list as $m_whom_list) { $m_img_list_whom = $m_whom_list->logo; }
}
if( $message_list->see == 0 ) { $ic_see = '<div class="icon"></div>'; } else { $ic_see = ''; }
$message_list_arr[] = '<div class="message-list-block" data-id="'.$message_list->from_id.'" data-type="'.$message_list->from_type.'" data-idw="'.$message_list->whom_id.'" data-typew="'.$message_list->whom_type.'"><img class="whom" src="'.$m_img_list_whom.'"><img src="'.$m_img_list_from.'"><p>'.$m_from_list.'</p>'.$ic_see.'</div>';
}
}
}
$message_list_el = array_unique($message_list_arr);
foreach($message_list_el as $message_list_el) { echo($message_list_el); }
echo('</div>');
таблица с такими полями:
- id
- from_id - id от кого пригло
- from_type - тип учетной записи от кого пришло
- whom_id - id кому пришло
- whom_type - тип учетной записи кому пришло
- time - когда написано
- message - текстовка
- see - 1/0 прочитано или нет
Ответы (2 шт):
Здесь нужно копать в сторону запроса в БД. Опираясь на структуру данных, если это SQL, Вы можете сделать запрос:
SELECT
from_id,
min(see) as see,
max(time) as time
FROM chat_messages
WHERE whom_id = $id
GROUP BY from_id
ORDER BY time DESC;
Здесь происходит группировка строк по полю from_id, тем самым получаем уникальные значения этого поля.
min(see) - получаем, какое значение минимальное, соответственно если есть хоть один 0, то это означает, что есть непрочитанные сообщения.
max(time) - получаем время последнего сообщения. На выходе получаем коллекцию (массив), элементы которого содержат поля:
- from_id - для отображения идентификатора чата (отправителя)
- see - 0/1, по которому решаем, показывать иконку или нет
- time - время последего сообщения
Если Вы хотите показать еще и текст последнего сообщения, то запрос будет чуть сложнее:
SELECT
from_id,
min(see) as see,
max(time) as time,
message
FROM (
SELECT
from_id,
see,
time,
message
FROM chat_messages
WHERE whom_id = $id
ORDER BY time DESC
) as t
GROUP BY from_id
ORDER BY time DESC;
Пример тут
Ну и в конце концов, в PHP мы просто проходимся по массиву с уже подготовленными данными и формируем HTML:
$chats_list = //result from sql request;
$chats_string = '';
foreach($chats_list as $chat) {
$icon = $chat['see'] ? '' : "<img src="path_to_icon">";
$time = $chat['time'];
$from = $chat['from_id'];
$message = $chat['message'];
$chats_string .= "<div>$icon $time $from - $message</div>";
}
И в конечном итоге, когда сообщений станет очень много, такие запросы будут работать долго. Поэтому, стоит задуматься о создании отдельной таблицы с чатами, где будет хранится общая информация по чату.
UPD: согласно комментария Во-первых, загружать себе всю всю таблицу из базы, чтобы потом фильтровать её в коде плохая практика. Вы вытаскиваете много лишней информации. Учитывая то, что Вы знаете, по каким критериям стоит фильтровать данные, используйте WHERE в Вашем запросе, это уменьшит объем трафика, использование оперативной памяти Вашим приложением и уменьшит количество кода для обработки.
Во-вторых, Вы в цикле делаете n запросов R::find, что чревато медленной работой и потенциально блокировкой таблиц. Соберите все параметры, по которым нужно сделать дополнительные запросы, и за один запрос к каждой таблице вытащите все что нужно из нее.
Если абстрагироваться от Вашей конкретной задачи и вернуться к массивам, то необходимо создать массив аккумулятор, после пройтись по массиву и в аккумулятор внести нужные данные:
$chats = [];
foreach($messages as $message) {
$from_id = $message['from_id'];
if (!isset($chats[$from_id])) {
$chats[$from_id] = // добавляем данные из сообщения;
} else {
// проверяем на прочитанное / непрочитанное, на последнее сообщение
}
}
выборку делаю по непрочитанным, фильтрую и проверяю есть ли в $chats id отправителя, и далее проверяю на прочтение для добавления иконки в общем вышло как-то так :
echo('<div class="message-list">');
$chats = [];
$message_list = R::findAll('messages', 'ORDER BY see ASC');
foreach ($message_list as $message_list) {
if( in_array($message_list->whom_id, $_SESSION['company']) && $message_list->whom_type == 'c' || in_array($message_list->from_id, $_SESSION['company']) && $message_list->from_type == 'd' ){
if( ( !in_array($message_list->from_id, $_SESSION['company']) && $message_list->from_type == 'c' ) || $message_list->from_type == 'u' ){
if ( !isset($chats[$message_list->from_id]) ) {
if( $message_list->from_type == 'u' ) {
$m_user_list = R::findOne('users', 'id= ?', [$message_list->from_id]);
$m_from_list = $m_user_list->name .' '. $m_user_list->surname;
$m_img_list_from = $m_user_list->avatar;
} else {
$m_user_list = R::findOne('companys', 'id= ?', [$message_list->from_id]);
$m_from_list = $m_user_list->name; $m_img_list_from = $m_user_list->logo;
}
if( $message_list->whom_type == 'u' ) {
$m_whom_list = R::findOne('users', 'id= ?', [$message_list->whom_id]);
$m_img_list_whom = $m_whom_list->avatar;
} else {
$m_whom_list = R::findOne('findOne', 'id= ?', [$message_list->whom_id]);
$m_img_list_whom = $m_whom_list->logo;
}
if( $message_list->see == 0 ) { $ic_see = '<div class="icon"></div>'; } else { $ic_see = ''; }
$message_list_arr[] = '<div class="message-list-block" data-id="'.$message_list->from_id.'" data-type="'.$message_list->from_type.'" data-idw="'.$message_list->whom_id.'" data-typew="'.$message_list->whom_type.'"><img class="whom" src="'.$m_img_list_whom.'"><img src="'.$m_img_list_from.'"><p>'.$m_from_list.'</p>'.$ic_see.'</div>';
}
}
}
}
$message_list_el = array_unique($message_list_arr);
foreach($message_list_el as $message_list_el) { echo($message_list_el); }
echo('</div>');
