IM
Чаты и участники
Рабочая справка по чатам Bitrix24 через PHP: ChatTable, RelationTable, получение чата, поиск по внешней сущности и участники чата.
В коробочном PHP чат лучше рассматривать как запись в ChatTable, а участников —
как записи в RelationTable. Сам чат и состав участников хранятся отдельно.
Чаты
Чат хранит общую информацию: ID, тип, название, внешнюю привязку, автора и служебные поля.
Что хранит ChatTable
Для чтения данных чата используется Bitrix\Im\Model\ChatTable. Это D7 ORM
таблица модуля im.
| Поле | Что означает |
|---|---|
ID | ID чата. В REST часто используется как chat123, а в таблицах — просто 123. |
TITLE | Название чата. |
TYPE | Тип чата: личный, групповой, открытая линия и другие варианты. |
ENTITY_TYPE | Внешний тип привязки, например CRM, TASKS или другой модуль. |
ENTITY_ID | Внешний ID привязки. Формат зависит от модуля. |
AUTHOR_ID | Создатель чата, если применимо. |
Получить чат по ID
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\ChatTable;
Loader::includeModule('im');
/**
* Получает чат по ID.
*/
function fetchChatById(int $chat_id): ?array
{
$chat = ChatTable::getList([
'select' => [
'ID',
'TITLE',
'TYPE',
'ENTITY_TYPE',
'ENTITY_ID',
'AUTHOR_ID',
],
'filter' => [
'=ID' => $chat_id,
],
'limit' => 1,
])->fetch();
return is_array($chat) ? $chat : null;
}
$chat = fetchChatById($chat_id);
print_r($chat);
Если ID пришёл из REST как chat123, перед запросом к таблице нужно убрать
префикс chat.
/**
* Преобразует dialog id в числовой ID чата.
*/
function parseChatId(string $dialog_id): int
{
if (preg_match('/^chat(\d+)$/', $dialog_id, $matches)) {
return (int) $matches[1];
}
return (int) $dialog_id;
}
$chat_id = parseChatId('chat123'); Найти чаты по внешней сущности
У чата может быть внешняя привязка через ENTITY_TYPE и
ENTITY_ID. Это удобно для поиска CRM-чата, task-чата или чата своего
модуля.
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\ChatTable;
Loader::includeModule('im');
/**
* Получает чаты по внешней сущности.
*/
function fetchChatsByEntity(string $entity_type, string $entity_id): array
{
$chats = [];
$chat_result = ChatTable::getList([
'select' => [
'ID',
'TITLE',
'TYPE',
'ENTITY_TYPE',
'ENTITY_ID',
],
'filter' => [
'=ENTITY_TYPE' => $entity_type,
'=ENTITY_ID' => $entity_id,
],
'order' => [
'ID' => 'DESC',
],
]);
while ($chat = $chat_result->fetch()) {
$chats[] = $chat;
}
return $chats;
}
$chats = fetchChatsByEntity('CRM', 'DEAL|123');
print_r($chats);
Формат ENTITY_ID зависит от источника. Для CRM, задач и открытых линий
лучше сначала вывести реальную запись чата и посмотреть значения на своём портале.
Участники
Участники чата хранятся отдельно от самого чата. Один чат — много записей в таблице связей.
Что хранит RelationTable
Для чтения участников используется Bitrix\Im\Model\RelationTable.
| Поле | Что означает |
|---|---|
CHAT_ID | ID чата. |
USER_ID | ID пользователя-участника. |
MESSAGE_TYPE | Тип диалога или сообщения для связи. |
STATUS | Статус участия. |
LAST_ID | Последнее прочитанное сообщение. |
COUNTER | Счётчик непрочитанных сообщений для пользователя. |
Получить участников чата
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\RelationTable;
use Bitrix\Main\UserTable;
Loader::includeModule('im');
/**
* Получает участников чата.
*/
function fetchChatUsers(int $chat_id): array
{
$users = [];
$relation_result = RelationTable::getList([
'select' => [
'CHAT_ID',
'USER_ID',
'STATUS',
'COUNTER',
'USER_NAME' => 'USER.NAME',
'USER_LAST_NAME' => 'USER.LAST_NAME',
'USER_LOGIN' => 'USER.LOGIN',
],
'filter' => [
'=CHAT_ID' => $chat_id,
],
'runtime' => [
'USER' => [
'data_type' => UserTable::class,
'reference' => [
'=this.USER_ID' => 'ref.ID',
],
],
],
'order' => [
'USER_ID' => 'ASC',
],
]);
while ($user = $relation_result->fetch()) {
$users[] = $user;
}
return $users;
}
$users = fetchChatUsers($chat_id);
print_r($users); Проверить участие пользователя
<?php
use Bitrix\Main\Loader;
use Bitrix\Im\Model\RelationTable;
Loader::includeModule('im');
/**
* Проверяет, состоит ли пользователь в чате.
*/
function hasUserInChat(int $chat_id, int $user_id): bool
{
$relation = RelationTable::getList([
'select' => [
'CHAT_ID',
'USER_ID',
],
'filter' => [
'=CHAT_ID' => $chat_id,
'=USER_ID' => $user_id,
],
'limit' => 1,
])->fetch();
return is_array($relation);
}
$has_user = hasUserInChat($chat_id, $user_id);
var_dump($has_user);
Для добавления и удаления участников лучше использовать штатные методы мессенджера или
REST-методы im.chat.user.*, а таблицы использовать в первую очередь для
чтения и диагностики.