В этом разделе мы постарались собрать полезные примеры по работе с сущностью.

Поиск по основным параметрам

Найти контакты, в имени которых есть буква “А”

\Bitrix\Main\Loader::requireModule('crm');

$contactResult = \CCrmContact::GetListEx(
    [],
    [
        '%NAME' => 'А',
        'CHECK_PERMISSIONS' => 'N'
    ],
    false,
    false,
    [
        'ID',
        'FULL_NAME'
    ]
);

while( $contact = $contactResult->fetch() )
{
    /**
     * [ 'ID' => ..., 'TITLE' => ... ]
     * @var array
     */
    var_dump($contact);
    var_dump($contact['ID']);
}

Найти все контакты у которых есть телефон

Архитектурно множественные поля, такие как телефон, email или мессенджеры хранятся в отдельной таблице и чтобы не выполнять лишних запросов при операциях над такими контактами созданы поля-прослойки, которые отмечают факт наличия определенных связей.

HAS_PHONE (Y/N) - Y в случае наличия хотя бы одного телефона HAS_EMAIL (Y/N) - Y в случае наличия хотя бы одной почты HAS_IMOL (Y/N) - Y в случае наличия хотя бы одного мессенджера

\Bitrix\Main\Loader::requireModule('crm');

$contactResult = \CCrmContact::GetListEx(
    [],
    [
        'HAS_PHONE' => 'Y',
        'CHECK_PERMISSIONS' => 'N'
    ],
    false,
    false,
    [
        'ID',
        'FULL_NAME'
    ]
);

while( $contact = $contactResult->fetch() )
{
    /**
     * [ 'ID' => ..., 'TITLE' => ... ]
     * @var array
     */
    var_dump($contact);
    var_dump($contact['ID']);
}

Множественные поля

Мы уже описали что Битрикс24 хранит множественные поля отдельно и часто возникает вопрос как работать с такими полями. Наиболее удобным способом является работа от API множественных полей.

Получение всех телефонов контакта

Задача: найти все телефонные номера контакта с ID:1

\Bitrix\Main\Loader::requireModule('crm');

$resFieldMulti = \CCrmFieldMulti::GetListEx(
    [],
    [
        'ENTITY_ID' => \CCrmOwnerType::ContactName,
        'ELEMENT_ID' => 1,
        'TYPE_ID' => \CCrmFieldMulti::PHONE
    ]
);

while( $multifield = $resFieldMulti->fetch() )
{
    /**
     * $multifield = [
     *     "ID" => string(1) "6",
     *     "ENTITY_ID" => string(7) "CONTACT",
     *     "ELEMENT_ID" => string(1) "1",
     *     "TYPE_ID" => string(5) "PHONE",
     *     "VALUE_TYPE" => string(4) "WORK",
     *     "COMPLEX_ID" => string(10) "PHONE_WORK"
     *     "VALUE" => string(9) "213 11 64"
     * ];
     */
}

Найти контакт по номеру телефона

Метод CCrmFieldMulti::GetListEx выглядит удобным для поиска контакта по телефонному номеру, однако это ошибочное мнение. Дело в том что таблица хранит в себе заданные пользователем значения as is (как есть), т.е. один телефонный номер может быть записан в нескольких вариантах, например:

  • 88002000600
  • +7 800 2000 600
  • 8 (800) 200-60-00

С точки зрения человека это один и тот же номер, но с точки зрения системы это совершенно разные строки.

Для данного метода поиск требует чтобы данные были проиндексированы менеджером дубликатов. В случае если поиск не производился или он устарел, данные будут некорректны.

Наиболее удобным является поиск по номеру телефона в системе дубликатов. Найдем все контакты, которые имеют номер 2131164:

\Bitrix\Main\Loader::requireModule('crm');

/**
 * Телефон который будем искать
 * @var string
 */
$phone = '2131164';

/**
 * Список всех ID контактов с этим телефонным номером
 * @var int[]
 */
$contactIds = [];


$adapter = \Bitrix\Crm\EntityAdapterFactory::create([
        'FM' => [
            'PHONE' => [
                ['VALUE' => $phone]
            ]
        ]
    ],
    \CCrmOwnerType::Contact
);

$dups = (new \Bitrix\Crm\Integrity\ContactDuplicateChecker())
    ->findDuplicates(
        $adapter,
        new \Bitrix\Crm\Integrity\DuplicateSearchParams([
            'FM.PHONE'
        ])
    );

foreach($dups as &$dup)
{
    if(!($dup instanceof \Bitrix\Crm\Integrity\Duplicate))
    {
        continue;
    }

    $entities = $dup->getEntities();
    if(!(is_array($entities) && !empty($entities)))
    {
        continue;
    }

    //Each entity type limited by 50 items
    foreach($entities as &$entity)
    {
        if(!($entity instanceof \Bitrix\Crm\Integrity\DuplicateEntity))
        {
            continue;
        }

        if ( $entity->getEntityTypeID() != \CCrmOwnerType::Contact)
        {
            continue;
        }

        $contactIds[] = $entity->getEntityID();
    }
}

Телефонный номер в таблице дубликатов хранится в виде строки состоящей из чисел, поэтому предавая ее на поиск в менеджере дубликатов предварительно нужно очистить ненужные символы.

Дата рождения

Найти контакты, день рождения которых сегодня

Иногда необходимо найти контакты чье день рождения выпадает на определенное число или месяц. Так как не все СУБД поддерживают частичный поиск по полям с типом дата, разработчики использовали иной подход к подсистеме хранения даты рождения. При изменении даты рождения исходное значение сохраняется в поле BIRTHDATE, в то время как на основании дня и месяца рождения вычисляется специальное число хранящееся в поле BIRTHDAY_SORT.

Таким образом, чтобы найти пользователя у которого день рождения выпадает на определенно число нужно:

  1. Сгенерировать число для данной даты
  2. Выполнить поиск числа по ключу BIRTHDAY_SORT

Для генерации сортировочного числа используется класс Bitrix\Crm\BirthdayReminder:

\Bitrix\Main\Loader::requireModule('crm');

$birthDate = date('d.m.Y');

$sort = \Bitrix\Crm\BirthdayReminder::prepareSorting($birthDate);

/**
 * Например при:
 * $birthDate = 29.06.2021;
 * 
 * Будет результат:
 * $sort = 189; 
 */

Остается только дополнить поиск:

$contactResult = \CCrmContact::GetListEx(
    [],
    [
        'BIRTHDAY_SORT' => $sort,
        'CHECK_PERMISSIONS' => 'N'
    ],
    false,
    false,
    [
        'ID',
        'FULL_NAME'
    ]
);

while( $contact = $contactResult->fetch() )
{
    /**
     * [ 'ID' => ..., 'TITLE' => ... ]
     * @var array
     */
    var_dump($contact);
    var_dump($contact['ID']);
}

Альтернативный вариант поиска контактов

Помимо изложенного выше пути существует и другой путь для поиска: через специальный метод getNearestEntities класса Bitrix\Crm\BirthdayReminder.

Сигнатура метода:

\Bitrix\Crm\BirthdayReminder::getNearestEntities(
    $entityID,
    $currentDate,
    $startDate = '',
    $responsibleID = 0,
    $intervalInDays = 7,
    $checkPermissions = true,
    $limit = 5
);
  • $entityID - тип сущности. Поддерживается \CCrmOwnerType::Lead и \CCrmOwnerType::Contact
  • $currentDate - текущая дата в формате сайта
  • $startDate - дата с которой нужно начинать поиск (в формате сайта)
  • $responsibleID - ID ответственного (если нужно), по-умолчанию - не учитывать
  • $intervalInDays - сколько дней от $startDate нужно вычислять
  • $checkPermissions - проверять права на просмотр
  • $limit - количество возвращаемых элементов
\Bitrix\Main\Loader::requireModule('crm');

$contacts = \Bitrix\Crm\BirthdayReminder::getNearestEntities(
    \CCrmOwnerType::Contact,
    date('d.m.Y'),
    date('d.m.Y', strtotime('+1day')),
    0,
    7,
    false,
    5
);

var_dump($contacts);

/**
 * Example: 
 * [
 *     [
 *         "ID" => string(1) "9",
 *         "BIRTHDATE" => string(10) "29.06.2021",
 *         "BIRTHDAY_SORT" => int(189)
 *         "HONORIFIC" => NULL,
 *         "NAME" => string(16) "Светлана",
 *         "SECOND_NAME" => string(0) "",
 *         "LAST_NAME" => string(16) "Копылова",
 *         "PHOTO" => NULL,
 *         "ENTITY_TYPE_ID" => int(3),
 *         "IMAGE_ID" => int(0),
 *         "IS_BIRTHDAY" => bool(true)
 *     ]
 * ]
 * 
 */