Введение
При разработке на коробочной версии Битрикс24 часто возникает задача программного получения комментариев к задачам. В отличие от REST API, где комментарии доступны через отдельные методы, в ядре комментарии задач хранятся в форумной подсистеме. Каждая задача имеет свой форумный топик (FORUM_TOPIC_ID) и форум (FORUM_ID), где сообщения и есть комментарии. Основным инструментом для чтения этих комментариев является метод CForumMessage::GetListEx.
Область применения и ключевые сущности
Метод CForumMessage::GetListEx используется для программного получения списка сообщений форума, в том числе комментариев задач. Понимание этой связки необходимо при:
- Экспорте данных задач — выгрузка всех комментариев во внешние системы
- Анализе коммуникаций — статистика по комментариям, анализ тональности
- Интеграции с чат-ботами — отправка уведомлений о новых комментариях
- Миграции данных — перенос комментариев из одной системы в другую
- Отчётах и дашбордах — подсчёт количества комментариев по задачам/исполнителям
Ключевые сущности:
| Таблица / Класс | Описание |
|---|---|
b_tasks_task
|
Задачи, содержит поля FORUM_ID и FORUM_TOPIC_ID
|
b_forum_topic
|
Топики форума, привязанные к задачам |
b_forum_message
|
Сообщения форума (комментарии) |
b_forum_file
|
Файлы, прикреплённые к сообщениям |
CTasks
|
Класс для работы с задачами |
CForumMessage
|
Класс для работы с сообщениями форума |
CForumFiles
|
Класс для работы с файлами форума |
Параметры метода CForumMessage::GetListEx
Метод имеет следующую сигнатуру:
phppublic static function GetListEx(
$arOrder = [],
$arFilter = [],
$arGroupBy = false,
$arNavStartParams = false,
$arSelect = []
)
Параметр $arOrder (сортировка)
Определяет порядок сортировки сообщений:
php$arOrder = [
'ID' => 'ASC', // по ID (возрастание)
'POST_DATE' => 'DESC' // по дате (убывание)
];
Доступные ключи: ID, POST_DATE, AUTHOR_ID, FORUM_ID, TOPIC_ID.
Параметр $arFilter (фильтрация)
Основные ключи для фильтрации комментариев задач:
| Ключ | Описание | Пример |
|---|---|---|
FORUM_ID
|
ID форума задачи |
$task['FORUM_ID']
|
TOPIC_ID
|
ID топика задачи |
$task['FORUM_TOPIC_ID']
|
!PARAM1
|
Исключение системных сообщений |
'TK' (убирает уведомления)
|
AUTHOR_ID
|
Фильтр по автору |
1
|
APPROVED
|
Статус модерации |
'Y'
|
!PARAM2
|
Исключение по дополнительным параметрам |
'UF_TASK_COMMENT'
|
Важный фильтр: !PARAM1 => 'TK' исключает системные сообщения задачи (уведомления о назначении, изменении статуса, сроках и т.д.), оставляя только пользовательские комментарии.
Параметр $arSelect (выбираемые поля)
Позволяет указать, какие поля возвращать. По умолчанию возвращаются все.
php$arSelect = [
'ID',
'POST_MESSAGE',
'POST_DATE',
'AUTHOR_ID',
'AUTHOR_NAME'
];
Практические примеры
Пример 1. Базовое получение всех комментариев задачи
phpuse Bitrix\Main\Loader;
Loader::includeModule('forum');
Loader::includeModule('tasks');
function getTaskComments(int $taskId): array
{
$arComments = [];
// 1. Получаем данные задачи
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
// 2. Параметры запроса
$filter = [
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK' // исключаем системные сообщения
];
$order = ['ID' => 'ASC'];
// 3. Получаем комментарии
$rsComments = CForumMessage::GetListEx($order, $filter);
while ($comment = $rsComments->Fetch()) {
$arComments[] = [
'ID' => $comment['ID'],
'AUTHOR_ID' => $comment['AUTHOR_ID'],
'AUTHOR_NAME' => $comment['AUTHOR_NAME'],
'DATE' => $comment['POST_DATE'],
'TEXT' => $comment['POST_MESSAGE']
];
}
return $arComments;
}
// Использование
$comments = getTaskComments(10278);
echo '<pre>'; print_r($comments); echo '</pre>';
Пример 2. Получение комментариев с файлами
phpfunction getCommentFiles(int $messageId): array
{
$files = [];
$rsFiles = CForumFiles::GetList([], ['MESSAGE_ID' => $messageId]);
while ($file = $rsFiles->Fetch()) {
$fileArray = \CFile::GetFileArray($file['FILE_ID']);
if ($fileArray) {
$files[] = [
'ID' => $fileArray['ID'],
'NAME' => $fileArray['ORIGINAL_NAME'],
'SIZE' => $fileArray['FILE_SIZE'],
'URL' => $fileArray['SRC']
];
}
}
return $files;
}
function getTaskCommentsWithFiles(int $taskId): array
{
$arComments = [];
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
$rsComments = CForumMessage::GetListEx(
['ID' => 'ASC'],
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK'
]
);
while ($comment = $rsComments->Fetch()) {
$arComments[] = [
'ID' => $comment['ID'],
'AUTHOR_ID' => $comment['AUTHOR_ID'],
'AUTHOR_NAME' => $comment['AUTHOR_NAME'],
'DATE' => $comment['POST_DATE'],
'TEXT' => $comment['POST_MESSAGE'],
'FILES' => getCommentFiles($comment['ID'])
];
}
return $arComments;
}
Пример 3. Получение только последних комментариев (сортировка по дате)
phpfunction getLastTaskComments(int $taskId, int $limit = 10): array
{
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
$rsComments = CForumMessage::GetListEx(
['POST_DATE' => 'DESC'], // сортируем от новых к старым
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK'
],
false, // без группировки
['nTopCount' => $limit] // ограничиваем количество
);
$comments = [];
while ($comment = $rsComments->Fetch()) {
$comments[] = [
'DATE' => $comment['POST_DATE'],
'TEXT' => $comment['POST_MESSAGE'],
'AUTHOR_NAME' => $comment['AUTHOR_NAME']
];
}
return $comments;
}
Пример 4. Фильтрация комментариев по автору
phpfunction getTaskCommentsByUser(int $taskId, int $userId): array
{
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
$rsComments = CForumMessage::GetListEx(
['ID' => 'ASC'],
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK',
'AUTHOR_ID' => $userId
]
);
$comments = [];
while ($comment = $rsComments->Fetch()) {
$comments[] = $comment['POST_MESSAGE'];
}
return $comments;
}
Пример 5. Получение всех комментариев с поиском по тексту
phpfunction searchInTaskComments(int $taskId, string $searchString): array
{
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
$rsComments = CForumMessage::GetListEx(
['ID' => 'ASC'],
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK',
'POST_MESSAGE' => '%' . $searchString . '%' // поиск по подстроке
]
);
$results = [];
while ($comment = $rsComments->Fetch()) {
$results[] = [
'ID' => $comment['ID'],
'TEXT' => $comment['POST_MESSAGE'],
'DATE' => $comment['POST_DATE']
];
}
return $results;
}
Пример 6. Получение комментариев с пагинацией
phpfunction getTaskCommentsPaginated(int $taskId, int $page = 1, int $perPage = 20): array
{
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return ['comments' => [], 'total' => 0];
}
$navParams = [
'nPageSize' => $perPage,
'iNumPage' => $page
];
$rsComments = CForumMessage::GetListEx(
['ID' => 'ASC'],
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK'
],
false,
$navParams
);
$comments = [];
while ($comment = $rsComments->Fetch()) {
$comments[] = $comment;
}
// Получаем общее количество
$rsComments->NavPrint();
$total = $rsComments->NavRecordCount ?? count($comments);
return [
'comments' => $comments,
'total' => $total,
'page' => $page,
'perPage' => $perPage,
'totalPages' => ceil($total / $perPage)
];
}
Пример 7. Получение комментариев за период
phpfunction getTaskCommentsByDateRange(int $taskId, string $dateFrom, string $dateTo): array
{
$task = CTasks::GetByID($taskId)->Fetch();
if (!$task || !$task['FORUM_TOPIC_ID'] || !$task['FORUM_ID']) {
return [];
}
$fromTS = MakeTimeStamp($dateFrom);
$toTS = MakeTimeStamp($dateTo);
$rsComments = CForumMessage::GetListEx(
['POST_DATE' => 'ASC'],
[
'FORUM_ID' => $task['FORUM_ID'],
'TOPIC_ID' => $task['FORUM_TOPIC_ID'],
'!PARAM1' => 'TK',
'>=POST_DATE' => ConvertTimeStamp($fromTS, 'FULL'),
'<=POST_DATE' => ConvertTimeStamp($toTS, 'FULL')
]
);
$comments = [];
while ($comment = $rsComments->Fetch()) {
$comments[] = [
'DATE' => $comment['POST_DATE'],
'TEXT' => $comment['POST_MESSAGE'],
'AUTHOR_NAME' => $comment['AUTHOR_NAME']
];
}
return $comments;
}
Альтернативные методы
| Метод | Описание |
|---|---|
CTaskComments::GetList()
|
Специализированный метод для комментариев задач, но внутри использует те же форумные таблицы. |
CForumMessage::GetByID()
|
Получение одного комментария по ID. |
CRest::call('task.commentitem.getlist')
|
REST API метод для получения комментариев (для облачной версии). |
CTasks::GetByID() → поле COMMENTS_COUNT
|
Получение только количества комментариев без их содержимого. |
Структура таблиц для справки
sql-- b_tasks_task (задачи) -- FORUM_ID, FORUM_TOPIC_ID -- b_forum_topic (топики) -- ID, FORUM_ID, TITLE -- b_forum_message (сообщения) -- ID, FORUM_ID, TOPIC_ID, AUTHOR_ID, POST_DATE, POST_MESSAGE, PARAM1, PARAM2 -- b_forum_file (файлы сообщений) -- ID, MESSAGE_ID, FILE_ID
Особенности и рекомендации
-
Обязательное подключение модулей: Перед вызовом методов необходимо подключить модули
forumиtasks. -
Исключение системных сообщений: Всегда используйте фильтр
'!PARAM1' => 'TK', если вам нужны только пользовательские комментарии. Без этого фильтра вы получите также уведомления о назначениях, изменениях статуса, сроках и т.д. -
Проверка наличия форумных данных: Не у всех задач может быть заполнен
FORUM_TOPIC_ID. Перед запросом всегда проверяйте наличие этих полей. -
Производительность: При массовом получении комментариев (для нескольких задач) рекомендуется использовать кеширование или агенты, так как запросы к форумным таблицам могут быть тяжёлыми.
-
Обработка BB-кодов: Текст комментария хранится с BB-кодами. Для вывода на сайте используйте
CForumMessage::GetText($comment['POST_MESSAGE'])или функциюhtmlspecialcharsEx(). -
Права доступа: Метод
CTasks::GetByIDвозвращает задачу только если у текущего пользователя есть права на её просмотр. При необходимости можно использовать параметр$skipPermissions = true. -
Системные комментарии (
PARAM2 = 'UF_TASK_COMMENT'): Для точной идентификации пользовательских комментариев можно также использовать фильтр'PARAM2' => 'UF_TASK_COMMENT'— именно это значение присваивается комментариям, оставленным через веб-интерфейс.
Заключение
CForumMessage::GetListEx — это основной метод для программного получения комментариев задач в коробочной версии Битрикс24. В связке с данными задачи из CTasks::GetByID он позволяет гибко фильтровать, сортировать и выбирать комментарии с прикреплёнными файлами. Понимание этой связки необходимо каждому разработчику, который работает с задачами на уровне ядра Битрикс, а не через REST API. Правильное использование фильтров (особенно !PARAM1 => 'TK') позволяет исключить системные уведомления и работать только с пользовательским контентом.
