CRM
Множественные поля
Работа с множественными полями CRM в коробочном Bitrix24: телефоны, e-mail, сайты, мессенджеры, CCrmFieldMulti, получение, добавление, изменение и удаление.
Телефон, e-mail, сайт и мессенджер — это не обычные поля карточки CRM. Они хранятся как
отдельные записи множественных полей и привязываются к лиду, контакту или компании через
ENTITY_ID и ELEMENT_ID.
Общее понимание
Множественные поля нужны там, где у одной CRM-карточки может быть несколько значений одного типа: несколько телефонов, несколько e-mail, несколько сайтов.
Что такое множественные поля
Множественное поле — это отдельная запись с типом, подтипом и значением. Например,
рабочий телефон контакта хранится как запись с TYPE_ID = PHONE,
VALUE_TYPE = WORK и самим номером в VALUE.
В карточке CRM эти значения выглядят как обычные телефоны и e-mail, но при работе через PHP их нужно получать и изменять отдельно.
Где они хранятся
Для работы с множественными полями в коробочном PHP используется
CCrmFieldMulti. Через него можно получить, добавить, изменить или удалить
телефон, e-mail, сайт или мессенджер.
| Что нужно | Класс | Метод |
|---|---|---|
| Получить значения | CCrmFieldMulti | GetList() |
| Добавить значение | CCrmFieldMulti | Add() |
| Изменить значение | CCrmFieldMulti | Update() |
| Удалить значение | CCrmFieldMulti | Delete() |
Типы полей
Тип лучше задавать через константы CCrmFieldMulti, а не строками руками.
| Константа | Что означает |
|---|---|
CCrmFieldMulti::PHONE | Телефон. |
CCrmFieldMulti::EMAIL | E-mail. |
CCrmFieldMulti::WEB | Сайт. |
CCrmFieldMulti::IM | Мессенджер. |
Получение
Для чтения множественных полей важно правильно указать владельца: тип CRM-сущности и ID карточки.
Получить все значения карточки
В множественных полях ENTITY_ID — это строковый код сущности:
LEAD, CONTACT, COMPANY. А ELEMENT_ID
— ID конкретной карточки.
<?php
use Bitrix\Main\Loader;
const CRM_CONTACT_ENTITY_NAME = 'CONTACT';
Loader::includeModule('crm');
/**
* Получает множественные поля CRM-карточки.
*/
function fetchMultifieldsByOwner(string $entity_name, int $element_id): array
{
$multifields = [];
$multifield_result = \CCrmFieldMulti::GetList(
[
'ID' => 'ASC',
],
[
'ENTITY_ID' => $entity_name,
'ELEMENT_ID' => $element_id,
]
);
while ($multifield = $multifield_result->Fetch()) {
$multifields[] = $multifield;
}
return $multifields;
}
$multifields = fetchMultifieldsByOwner(CRM_CONTACT_ENTITY_NAME, $contact_id);
print_r($multifields); Получить телефоны
Чтобы получить только телефоны, добавляем фильтр по TYPE_ID.
<?php
use Bitrix\Main\Loader;
const CRM_CONTACT_ENTITY_NAME = 'CONTACT';
Loader::includeModule('crm');
/**
* Получает телефоны CRM-карточки.
*/
function fetchPhoneMultifields(string $entity_name, int $element_id): array
{
$phones = [];
$multifield_result = \CCrmFieldMulti::GetList(
[
'ID' => 'ASC',
],
[
'ENTITY_ID' => $entity_name,
'ELEMENT_ID' => $element_id,
'TYPE_ID' => \CCrmFieldMulti::PHONE,
]
);
while ($phone = $multifield_result->Fetch()) {
$phones[] = $phone;
}
return $phones;
}
$phones = fetchPhoneMultifields(CRM_CONTACT_ENTITY_NAME, $contact_id);
print_r($phones);
Для e-mail, сайта и мессенджера меняется только TYPE_ID:
CCrmFieldMulti::EMAIL, CCrmFieldMulti::WEB,
CCrmFieldMulti::IM.
Найти карточки с телефоном или почтой
У лидов, контактов и компаний есть служебные признаки вроде HAS_PHONE и
HAS_EMAIL. Их удобно использовать, когда нужно найти карточки, у которых
вообще есть телефон или e-mail, не вытаскивая сразу все значения.
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
Loader::includeModule('crm');
/**
* Получает контакты, у которых есть телефон.
*/
function fetchContactsWithPhone(): array
{
$factory = Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
if ($factory === null) {
return [];
}
return $factory->getItems([
'select' => [
'ID',
'NAME',
'LAST_NAME',
'HAS_PHONE',
'HAS_EMAIL',
],
'filter' => [
'=HAS_PHONE' => 'Y',
],
'order' => [
'ID' => 'ASC',
],
'limit' => 100,
]);
}
$contacts = fetchContactsWithPhone();
foreach ($contacts as $contact) {
print_r($contact->toArray());
} Такой фильтр не возвращает сами номера. Он только помогает найти карточки, у которых есть хотя бы одно значение нужного типа.
Изменение
Для изменения множественных полей используется ID конкретной записи множественного поля. Это не ID контакта, компании или лида.
Добавить значение
Пример добавляет рабочий телефон контакта.
<?php
use Bitrix\Main\Loader;
const CRM_CONTACT_ENTITY_NAME = 'CONTACT';
Loader::includeModule('crm');
/**
* Добавляет множественное поле CRM.
*/
function addMultifield(
string $entity_name,
int $element_id,
string $type_id,
string $value_type,
string $value
): int {
$field_multi = new \CCrmFieldMulti();
$multifield_id = $field_multi->Add(
[
'ENTITY_ID' => $entity_name,
'ELEMENT_ID' => $element_id,
'TYPE_ID' => $type_id,
'VALUE_TYPE' => $value_type,
'VALUE' => $value,
],
[
'ENABLE_NOTIFICATION' => true,
]
);
return (int) $multifield_id;
}
$phone_id = addMultifield(
CRM_CONTACT_ENTITY_NAME,
$contact_id,
\CCrmFieldMulti::PHONE,
'WORK',
'+7 999 111-22-33'
); Изменить значение
Для обновления нужен ID записи множественного поля. Его можно получить
через GetList().
<?php
use Bitrix\Main\Loader;
Loader::includeModule('crm');
/**
* Изменяет множественное поле CRM.
*/
function updateMultifield(int $multifield_id, string $value_type, string $value): bool
{
$field_multi = new \CCrmFieldMulti();
$is_updated = $field_multi->Update(
$multifield_id,
[
'VALUE_TYPE' => $value_type,
'VALUE' => $value,
],
[
'ENABLE_NOTIFICATION' => true,
]
);
return (bool) $is_updated;
}
$is_updated = updateMultifield(
$multifield_id,
'WORK',
'+7 999 555-44-33'
); Удалить значение
Удаление выполняется по ID записи множественного поля.
<?php
use Bitrix\Main\Loader;
Loader::includeModule('crm');
/**
* Удаляет множественное поле CRM.
*/
function deleteMultifield(int $multifield_id): bool
{
$field_multi = new \CCrmFieldMulti();
$is_deleted = $field_multi->Delete(
$multifield_id,
[
'ENABLE_NOTIFICATION' => true,
]
);
return (bool) $is_deleted;
}
$is_deleted = deleteMultifield($multifield_id); Заменить телефоны карточки
Если нужно заменить все телефоны карточки, сначала получаем текущие телефоны, удаляем их, затем добавляем новые значения.
<?php
use Bitrix\Main\Loader;
const CRM_CONTACT_ENTITY_NAME = 'CONTACT';
Loader::includeModule('crm');
/**
* Получает множественные поля нужного типа.
*/
function fetchMultifieldsByType(string $entity_name, int $element_id, string $type_id): array
{
$multifields = [];
$multifield_result = \CCrmFieldMulti::GetList(
[
'ID' => 'ASC',
],
[
'ENTITY_ID' => $entity_name,
'ELEMENT_ID' => $element_id,
'TYPE_ID' => $type_id,
]
);
while ($multifield = $multifield_result->Fetch()) {
$multifields[] = $multifield;
}
return $multifields;
}
/**
* Удаляет множественное поле.
*/
function deleteMultifield(int $multifield_id): bool
{
$field_multi = new \CCrmFieldMulti();
return (bool) $field_multi->Delete(
$multifield_id,
[
'ENABLE_NOTIFICATION' => true,
]
);
}
/**
* Добавляет множественное поле.
*/
function addMultifield(
string $entity_name,
int $element_id,
string $type_id,
string $value_type,
string $value
): int {
$field_multi = new \CCrmFieldMulti();
return (int) $field_multi->Add(
[
'ENTITY_ID' => $entity_name,
'ELEMENT_ID' => $element_id,
'TYPE_ID' => $type_id,
'VALUE_TYPE' => $value_type,
'VALUE' => $value,
],
[
'ENABLE_NOTIFICATION' => true,
]
);
}
/**
* Заменяет телефоны CRM-карточки.
*/
function replacePhoneMultifields(string $entity_name, int $element_id, array $phone_values): void
{
$old_phones = fetchMultifieldsByType(
$entity_name,
$element_id,
\CCrmFieldMulti::PHONE
);
foreach ($old_phones as $old_phone) {
deleteMultifield((int) $old_phone['ID']);
}
foreach ($phone_values as $phone_value) {
addMultifield(
$entity_name,
$element_id,
\CCrmFieldMulti::PHONE,
'WORK',
$phone_value
);
}
}
replacePhoneMultifields(
CRM_CONTACT_ENTITY_NAME,
$contact_id,
[
'+7 999 111-22-33',
'+7 999 555-44-33',
]
); Поля
Основные поля записи множественного поля и значения, которые чаще всего приходится использовать в фильтрах.
Основные поля записи
| Поле | Что означает |
|---|---|
ID | ID записи множественного поля. |
ENTITY_ID | Строковый тип владельца: LEAD, CONTACT, COMPANY. |
ELEMENT_ID | ID карточки CRM. |
TYPE_ID | Тип значения: PHONE, EMAIL, WEB, IM. |
VALUE_TYPE | Подтип значения: рабочий, домашний, мобильный и т. д. |
COMPLEX_ID | Составной код вида PHONE_WORK или EMAIL_HOME. |
VALUE | Само значение: номер телефона, e-mail, сайт или идентификатор мессенджера. |
VALUE_TYPE
VALUE_TYPE уточняет назначение значения. Для телефона это может быть
рабочий, мобильный или домашний номер. Для e-mail — рабочая или домашняя почта.
| VALUE_TYPE | Когда использовать |
|---|---|
WORK | Рабочий телефон, e-mail или сайт. |
HOME | Домашний телефон или e-mail. |
MOBILE | Мобильный телефон. |
OTHER | Другое значение, если точный тип не подходит. |
Список доступных подтипов может отличаться в зависимости от типа поля и версии портала.
Для служебного скрипта обычно достаточно сначала вывести уже существующие записи и
посмотреть, какие VALUE_TYPE используются на портале.
ENTITY_ID и ELEMENT_ID
Самая частая ошибка — передать в ENTITY_ID числовой тип
CCrmOwnerType::Contact. В множественных полях туда нужен строковый код
сущности.
| Карточка | ENTITY_ID | ELEMENT_ID |
|---|---|---|
| Лид | LEAD | ID лида. |
| Контакт | CONTACT | ID контакта. |
| Компания | COMPANY | ID компании. |
У сделки обычно нет собственных телефонов и e-mail как у клиента. Телефоны и почта обычно находятся у связанного контакта, компании или лида.