Блог разработчика 1С-Битрикс

Руководство по работе с классом \Bitrix\Main\UserUtils в Битрикс D7

В современных версиях 1С-Битрикс всё активнее внедряется концепция D7, позволяющая писать код более структурированно и гибко. Класс \Bitrix\Main\UserUtils — это часть ядра (bitrix/modules/main/lib/userutils.php), содержащая утилиты для работы с пользователями. Он упрощает поиск пользователей по персональным данным, получение информации о подразделениях и решает ряд распространённых задач, связанных с данными пользователей.

Работа с классом \Bitrix\Main\UserUtils

В данной статье мы разберём самые востребованные методы класса UserUtils, а также приведём практические примеры их использования. Материал рассчитан на разработчиков, которые работают с D7 и хотят упростить написание кода, связанного с пользователями.

Содержание

  1. Обзор класса \Bitrix\Main\UserUtils
  2. Метод getUserSearchFilter
  3. Метод getDepartmentNames
  4. Метод getDepartmentName
  5. Дополнительные советы и рекомендации

1. Обзор класса \Bitrix\Main\UserUtils

Класс \Bitrix\Main\UserUtils находится в файле:

bitrix/modules/main/lib/userutils.php

Основные возможности, которые он предоставляет:

  • Формирование фильтров для поиска пользователей (учитывая возможности полнотекстового поиска).
  • Получение информации о подразделениях (одного или нескольких) с локализованными названиями.
  • Вспомогательные функции для обработки пользовательских полей (UF) и тегов в контексте модуля socialnetwork.

Класс ориентирован на новую методологию D7 и позволяет удобно работать совместно с ORM-таблицей \Bitrix\Main\UserTable.

2. Метод getUserSearchFilter

Метод:

\Bitrix\Main\UserUtils::getUserSearchFilter(array $fields)

Позволяет получить корректно сформированный массив для фильтрации в \Bitrix\Main\UserTable::getList() по полям с персональными данными. Под капотом метод учитывает возможности полнотекстового поиска (Fulltext Index), а при его отсутствии имитирует логику через LIKE.

Описание работы и параметры

  • Параметр
    • fields (массив) — задаётся в любом сочетании:
      • NAME — имя;
      • LAST_NAME — фамилия;
      • SECOND_NAME — отчество;
      • WORK_POSITION — должность;
      • UF_DEPARTMENT_NAME — название подразделения.
      • Альтернативно можно использовать ключ FIND, где вы задаёте строку поиска, которая будет биться одновременно по всем вышеперечисленным полям. Это аналог старого фильтра NAME_SEARCH в классе CUser.
  • Возвращаемое значение
    • Массив, подходящий для использования в секции 'filter' в методе \Bitrix\Main\UserTable::getList().
  • Особенности
    • Если в системе включен полнотекстовый поиск по таблице UserIndexTable и он поддерживает SEARCH_USER_CONTENT, то фильтр будет формироваться с использованием *INDEX.SEARCH_USER_CONTENT или *INDEX.SEARCH_DEPARTMENT_CONTENT.
    • Если полнотекстовый поиск недоступен, фильтрация будет эмулироваться с помощью конструкции LIKE и логики AND/OR для каждого слова, разделённого пробелом.

Пример использования

Рассмотрим ситуацию, когда нужно найти всех пользователей, в чьих персональных данных (фамилия, имя, отчество, должность или подразделение) есть строка «Мария Ившина», а также отфильтровать только реальных пользователей (поле IS_REAL_USER = 'Y'):

use Bitrix\Main\UserUtils;
use Bitrix\Main\UserTable;

$filter = UserUtils::getUserSearchFilter([
    'FIND' => 'Мария Ившина'
]);

// Добавим дополнительное условие (пример):
$filter['IS_REAL_USER'] = 'Y';

// Получаем пользователей
$records = UserTable::getList([
    'select' => ['ID', 'NAME', 'SECOND_NAME', 'LAST_NAME', 'WORK_POSITION', 'UF_DEPARTMENT'],
    'filter' => $filter
])->fetchAll();

// Результат — массив пользователей
print_r($records);

Приведённый пример вернёт список пользователей, в полях которых содержится упоминание «Мария» или «Ившина» (а иногда и обе части). Если полнотекстовый поиск включён и правильно настроен, результат будет корректен и более быстрый. Если же нет, код будет применять логику поиска через LIKE.

  1. Наличие индекса. Чтобы полнотекстовый поиск работал, необходимо, чтобы в таблице UserIndexTable были сформированы соответствующие индексы (SEARCH_USER_CONTENT, SEARCH_DEPARTMENT_CONTENT и т.д.).
  2. Подготовка запросов. Под капотом класс проверяет, является ли токен (строка поиска) целым числом (isIntegerToken) или же обычным текстом. В зависимости от этого формируется соответствующая «строка» для поиска.
  3. Автоматический fallback. Если по какой-то причине полнотекстовый поиск недоступен (например, MySQL не поддерживает нужные типы индексов или они не сформированы), метод автоматически переключается на режим поиска с помощью LIKE.

3. Метод getDepartmentNames

Метод:

\Bitrix\Main\UserUtils::getDepartmentNames(array $departmentIds)

Описание работы и параметры

  • Параметр
    • departmentIds — массив идентификаторов подразделений из поля UF_DEPARTMENT в \Bitrix\Main\UserTable. Каждый элемент массива — это ID подразделения в структуре компании (если установлен модуль «Интранет»).
  • Возвращаемое значение
    • Массив данных о подразделениях, где каждый элемент содержит информацию: ID, NAME, DEPTH_LEVEL, IBLOCK_SECTION_ID и т.д. Таким образом вы получаете «локализованное» название и при желании можете восстановить иерархию структуры.
  • Важно
    • Метод использует кеширование (TagCache) и обращается к инфоблоку структуры компании.
    • Если модуль «Интранет» не установлен или не настроен, метод вернёт пустой массив.
    • По умолчанию метод работает с опцией intranet:iblock_structure, которая хранит ID инфоблока структуры компании.

Пример использования

use Bitrix\Main\UserUtils;

// Допустим, у пользователя в UF_DEPARTMENT может быть несколько подразделений
$departments = [1,2,3];

$result = UserUtils::getDepartmentNames($departments);

if (!empty($result))
{
    foreach ($result as $departmentInfo)
    {
        echo "ID: " . $departmentInfo['ID'] . "\n";
        echo "Название: " . $departmentInfo['NAME'] . "\n";
        echo "Уровень: " . $departmentInfo['DEPTH_LEVEL'] . "\n";
        echo "Родительский раздел: " . $departmentInfo['IBLOCK_SECTION_ID'] . "\n";
        echo "---------------\n";
    }
}

В результате вы получите набор данных о каждом подразделении с учётом его текущего названия, вложенности и т.д. При необходимости можно модифицировать логику, чтобы отобразить иерархическое «дерево» внутри компании.

4. Метод getDepartmentName

Метод:

\Bitrix\Main\UserUtils::getDepartmentName($departmentId)

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

Описание работы и параметры

  • Параметр
    • departmentId (число) — идентификатор подразделения (например, из поля UF_DEPARTMENT пользователя).
  • Возвращаемое значение
    • Первым элементом массива возвращается информация о подразделении (аналогичная результатам getDepartmentNames), либо false, если подразделение не найдено.

Пример использования

use Bitrix\Main\UserUtils;

$departmentId = 3;
$result = UserUtils::getDepartmentName($departmentId);

if ($result !== false)
{
    echo "ID: " . $result['ID'] . "\n";
    echo "Название: " . $result['NAME'] . "\n";
}
else
{
    echo "Подразделение с таким ID не найдено или модуль «Интранет» не установлен.\n";
}

Если подразделение имеется в структуре компании, вы получите информацию о нём: ID, NAME и прочие поля.

5. Дополнительные советы и рекомендации

  1. Актуальность данных. При использовании методов для подразделений (getDepartmentNames/getDepartmentName) учитывайте, что данные о структуре компании могут меняться. Если что-то в инфоблоке структуры поменялось, обновится и кеш. Но если это происходит редко, вы сможете полагаться на кешированные данные.
  2. Использование в связке с \Bitrix\Main\UserTable.
    • При формировании сложных фильтров (например, поиск по нескольким критериям, включающим поля, которых нет в UserUtils), вы можете комбинировать полученный массив фильтра с другими условиями.
    • Обязательно проверяйте, что нужные поля у пользователя существуют (некоторые UF могут отсутствовать, если не настроены в админке).
  3. Оптимизация.
    • Если у вас в проекте очень большое количество пользователей, следите за тем, чтобы поисковые индексы были актуальными. Это ускорит работу методов getUserSearchFilter.
    • Если вы используете старый модуль CUser, стоит постепенно переходить на D7-ориентированные классы, такие как \Bitrix\Main\UserTable и \Bitrix\Main\UserUtils, чтобы иметь более гибкую систему управления запросами.
  4. Доработка методов.
    • Код в UserUtils можно расширять: вы можете смотреть на исходники, при необходимости переопределять логику в своих классах-утилитах. Однако старайтесь не менять файлы ядра напрямую. Лучше использовать наследование или собственные классы, чтобы обеспечить поддержку обновлений Битрикс.

Заключение

Класс \Bitrix\Main\UserUtils — полезный и гибкий инструмент в 1С-Битрикс (D7) для поиска и работы с данными пользователей. Он помогает:

  • упростить логику формирования фильтров в UserTable::getList();
  • получать названия подразделений пользователей из структуры компании;
  • эффективно использовать возможности полнотекстового поиска.

Рекомендуется внимательно изучить исходный код класса (расположен по пути bitrix/modules/main/lib/userutils.php) и комбинировать методы UserUtils с иными инструментами D7, чтобы в полной мере использовать все преимущества новой архитектуры.

Надеемся, что данное руководство окажется полезным и сэкономит ваше время при настройке и доработке порталов на 1С-Битрикс!

Теги: D7, \Bitrix\Main\UserUtils, пользователи, подразделения, полнотекстовый поиск


Валерий Макеев
04.09.2025 11:23
Пример кода, который безопасно ищет пользователей по ФИО с помощью UserUtils::getUserSearchFilter, корректно обрабатывает отсутствие поля UF_DEPARTMENT при неустановленном модуле «Интранет» и выводит данные о пользователях, включая подразделения — только если они доступны.
Код
<?php
require $_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/prolog_before.php';

use Bitrix\Main\UserUtils;
use Bitrix\Main\UserTable;
use Bitrix\Main\Loader;
use Bitrix\Main\UserFieldTable;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

if (!Loader::includeModule('main')) {
    die('Модуль "main" не загружен');
}

// === 1. Проверяем, существует ли поле UF_DEPARTMENT ===
$ufDepartmentExists = false;
try {
    $field = UserFieldTable::getList([
        'filter' => ['ENTITY_ID' => 'USER', 'FIELD_NAME' => 'UF_DEPARTMENT']
    ])->fetch();

    $ufDepartmentExists = !empty($field);
} catch (\Exception $e) {
    // Поле может не существовать — это нормально
    $ufDepartmentExists = false;
}

// === 2. Формируем фильтр поиска ===
$searchString = 'Troy Adams'; // Пример строки поиска

$filter = UserUtils::getUserSearchFilter([
    'FIND' => $searchString
]);

$filter['ACTIVE'] = 'Y';
$filter['IS_REAL_USER'] = 'Y';

// === 3. Формируем SELECT в зависимости от наличия UF_DEPARTMENT ===
$select = ['ID', 'NAME', 'LAST_NAME', 'SECOND_NAME', 'WORK_POSITION'];

if ($ufDepartmentExists) {
    $select[] = 'UF_DEPARTMENT';
}

// === 4. Выполняем запрос ===
try {
    $users = UserTable::getList([
        'select' => $select,
        'filter' => $filter,
        'limit' => 10
    ])->fetchAll();
} catch (\Exception $e) {
    die('Ошибка при получении пользователей: ' . $e->getMessage());
}

// === 5. Вывод результатов ===
foreach ($users as $user) {
    echo "<h3>";
    echo htmlspecialcharsbx($user['LAST_NAME'] ?? '') . ' ';
    echo htmlspecialcharsbx($user['NAME'] ?? '');
    if (!empty($user['SECOND_NAME'])) {
        echo ' ' . htmlspecialcharsbx($user['SECOND_NAME']);
    }
    echo "</h3>";

    echo "<p><strong>Должность:</strong> ";
    echo !empty($user['WORK_POSITION']) ? htmlspecialcharsbx($user['WORK_POSITION']) : 'не указана';
    echo "</p>";

    // === 6. Показываем подразделения ТОЛЬКО если поле существует и установлен модуль intranet ===
    if ($ufDepartmentExists && !empty($user['UF_DEPARTMENT']) && is_array($user['UF_DEPARTMENT'])) {
        // Попробуем подключить intranet для getDepartmentNames
        if (Loader::includeModule('intranet')) {
            $departments = UserUtils::getDepartmentNames($user['UF_DEPARTMENT']);
            if (!empty($departments)) {
                echo "<p><strong>Подразделения:</strong></p><ul>";
                foreach ($departments as $dept) {
                    echo "<li>";
                    echo str_repeat(' ', ($dept['DEPTH_LEVEL'] - 1) * 4);
                    echo htmlspecialcharsbx($dept['NAME']);
                    echo " (ID: {$dept['ID']})";
                    echo "</li>";
                }
                echo "</ul>";
            }
        } else {
            echo "<p><em>Подразделения: данные доступны, но модуль «Интранет» не установлен — не могу отобразить названия.</em></p>";
        }
    } else {
        echo "<p><strong>Подразделения:</strong> не назначены или недоступны</p>";
    }

    echo "<hr>";
}

Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Аутсорсинг

готов помочь, если нет времени

договорная

Могу взять на себя работы по full-stack

* на основе готовой верстки

Лендинг

от 3 дней

от 25 000 рублей

Разработка одностраничного сайта на платформе Битрикс

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Техническая поддержка

выполняется с сайтами на основе любых CMS

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

* стоимость зависит от объема и сложности выполняемых работ, используемой CMS.