CRM
Контакты
Работа с контактами CRM через PHP и фабрики: получение, добавление, изменение, удаление, связь с компаниями и события.
Контакт — CRM-сущность для физического лица. Через фабрику удобно работать с основными полями контакта, а связь с компаниями хранится отдельно.
Основные операции
Базовая работа с контактами через фабрику CRM.
Получить контакт
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
Loader::includeModule('crm');
/**
* Получает фабрику контактов.
*/
function fetchContactFactory()
{
return Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
}
/**
* Получает контакт по ID.
*/
function fetchContactItem(int $contact_id)
{
$factory = fetchContactFactory();
if ($factory === null) {
return null;
}
return $factory->getItem($contact_id);
}
$contact_item = fetchContactItem($contact_id);
if ($contact_item !== null) {
$contact_data = $contact_item->toArray();
$name = $contact_item->get('NAME');
$last_name = $contact_item->get('LAST_NAME');
print_r($contact_data);
} Получить список контактов
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
const CONTACT_LIMIT = 100;
Loader::includeModule('crm');
/**
* Получает фабрику контактов.
*/
function fetchContactFactory()
{
return Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
}
/**
* Получает список контактов.
*/
function fetchContactItems(int $last_contact_id): array
{
$factory = fetchContactFactory();
if ($factory === null) {
return [];
}
return $factory->getItems([
'select' => [
'ID',
'NAME',
'LAST_NAME',
'SECOND_NAME',
'COMPANY_ID',
'ASSIGNED_BY_ID',
'DATE_CREATE',
],
'filter' => [
'>ID' => $last_contact_id,
],
'order' => [
'ID' => 'ASC',
],
'limit' => CONTACT_LIMIT,
]);
}
$contact_items = fetchContactItems(0);
foreach ($contact_items as $contact_item) {
print_r($contact_item->toArray());
} Добавить контакт
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
Loader::includeModule('crm');
/**
* Получает фабрику контактов.
*/
function fetchContactFactory()
{
return Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
}
/**
* Создаёт контакт.
*/
function addContact(string $name, string $last_name, int $assigned_by_id, int $company_id = 0): array
{
$factory = fetchContactFactory();
if ($factory === null) {
return [
'is_success' => false,
'contact_id' => 0,
'error_messages' => ['Фабрика контактов не найдена'],
];
}
$contact_item = $factory->createItem([
'NAME' => $name,
'LAST_NAME' => $last_name,
'ASSIGNED_BY_ID' => $assigned_by_id,
'COMPANY_ID' => $company_id,
]);
$operation = $factory->getAddOperation($contact_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'contact_id' => (int) $contact_item->getId(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$add_result = addContact($name, $last_name, $assigned_by_id, $company_id);
print_r($add_result); Изменить контакт
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
Loader::includeModule('crm');
/**
* Получает фабрику контактов.
*/
function fetchContactFactory()
{
return Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
}
/**
* Изменяет ФИО контакта.
*/
function updateContactName(int $contact_id, string $name, string $last_name): array
{
$factory = fetchContactFactory();
if ($factory === null) {
return [
'is_success' => false,
'error_messages' => ['Фабрика контактов не найдена'],
];
}
$contact_item = $factory->getItem($contact_id);
if ($contact_item === null) {
return [
'is_success' => false,
'error_messages' => ['Контакт не найден'],
];
}
$contact_item->set('NAME', $name);
$contact_item->set('LAST_NAME', $last_name);
$operation = $factory->getUpdateOperation($contact_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$update_result = updateContactName($contact_id, $name, $last_name);
print_r($update_result); Удалить контакт
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_CONTACT_TYPE_ID = \CCrmOwnerType::Contact;
Loader::includeModule('crm');
/**
* Получает фабрику контактов.
*/
function fetchContactFactory()
{
return Service\Container::getInstance()->getFactory(CRM_CONTACT_TYPE_ID);
}
/**
* Удаляет контакт.
*/
function deleteContact(int $contact_id): array
{
$factory = fetchContactFactory();
if ($factory === null) {
return [
'is_success' => false,
'error_messages' => ['Фабрика контактов не найдена'],
];
}
$contact_item = $factory->getItem($contact_id);
if ($contact_item === null) {
return [
'is_success' => false,
'error_messages' => ['Контакт не найден'],
];
}
$operation = $factory->getDeleteOperation($contact_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$delete_result = deleteContact($contact_id);
print_r($delete_result); Связи
Контакт может быть связан с компанией.
Компании контакта
Поле COMPANY_ID удобно для одной связи с компанией. Если нужно работать со всеми
связями контакта и компаний, лучше смотреть в сторону
ContactCompanyTable.
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Binding\ContactCompanyTable;
Loader::includeModule('crm');
/**
* Получает ID компаний контакта.
*/
function fetchContactCompanyIds(int $contact_id): array
{
return ContactCompanyTable::getContactCompanyIDs($contact_id);
}
/**
* Привязывает контакт к компаниям.
*/
function bindContactCompanies(int $contact_id, array $company_ids): void
{
ContactCompanyTable::bindCompanyIDs($contact_id, $company_ids);
}
$company_ids = fetchContactCompanyIds($contact_id);
print_r($company_ids); События
События контактов позволяют выполнить свой PHP-код перед добавлением, после добавления, перед изменением, после изменения, перед удалением и после удаления контакта.
Список событий
Обработчики обычно регистрируют в /local/php_interface/init.php или внутри
своего модуля. Для коробочной разработки это удобный способ реагировать на изменения
контактов без REST-приложения.
| Событие | Когда вызывается | Метод |
|---|---|---|
OnBeforeCrmContactAdd | Перед добавлением контакта. | CCrmContact::Add |
OnAfterCrmContactAdd | После добавления контакта. | CCrmContact::Add |
OnBeforeCrmContactUpdate | Перед изменением контакта. | CCrmContact::Update |
OnAfterCrmContactUpdate | После изменения контакта. | CCrmContact::Update |
OnBeforeCrmContactDelete | Перед удалением контакта. | CCrmContact::Delete |
OnAfterCrmContactDelete | После удаления контакта. | CCrmContact::Delete |
OnAfterExternalCrmContactAdd | После добавления внешнего контакта. | CCrmContact::Add |
Перед добавлением
В OnBeforeCrmContactAdd можно изменить поля до сохранения или отменить
создание контакта. Например, можно запретить создание полностью пустого контакта.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
/**
* Регистрирует обработчик перед добавлением контакта.
*/
function registerBeforeContactAddHandler(EventManager $event_manager): void
{
$event_manager->addEventHandlerCompatible(
'crm',
'OnBeforeCrmContactAdd',
'handleBeforeContactAdd'
);
}
/**
* Обрабатывает поля перед добавлением контакта.
*/
function handleBeforeContactAdd(array &$contact_fields): bool
{
global $APPLICATION;
$name = trim((string) ($contact_fields['NAME'] ?? ''));
$last_name = trim((string) ($contact_fields['LAST_NAME'] ?? ''));
if ($name === '' && $last_name === '') {
$APPLICATION->ThrowException('Не заполнены имя или фамилия контакта');
return false;
}
if (empty($contact_fields['OPENED'])) {
$contact_fields['OPENED'] = 'N';
}
return true;
}
registerBeforeContactAddHandler($event_manager);
В событиях до сохранения массив полей передаётся по ссылке. Если изменить значение в
$contact_fields, оно попадёт в сохраняемый контакт.
После изменения
OnAfterCrmContactUpdate удобно использовать для логирования, синхронизации
со своими таблицами или запуска вспомогательной логики после изменения контакта.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
/**
* Регистрирует обработчик после изменения контакта.
*/
function registerAfterContactUpdateHandler(EventManager $event_manager): void
{
$event_manager->addEventHandlerCompatible(
'crm',
'OnAfterCrmContactUpdate',
'handleAfterContactUpdate'
);
}
/**
* Обрабатывает изменение контакта.
*/
function handleAfterContactUpdate(array &$contact_fields): void
{
$contact_id = isset($contact_fields['ID']) ? (int) $contact_fields['ID'] : 0;
if ($contact_id <= 0) {
return;
}
AddMessage2Log(
[
'message' => 'Контакт изменён',
'contact_id' => $contact_id,
'fields' => $contact_fields,
],
'contact_events'
);
}
registerAfterContactUpdateHandler($event_manager);
Событие после изменения не всегда содержит полный набор полей контакта. Если нужно
проверить поле, которого нет в $contact_fields, лучше отдельно получить
контакт по ID.
Перед удалением
OnBeforeCrmContactDelete можно использовать, если удаление нужно проверить
или запретить.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
/**
* Регистрирует обработчик перед удалением контакта.
*/
function registerBeforeContactDeleteHandler(EventManager $event_manager): void
{
$event_manager->addEventHandlerCompatible(
'crm',
'OnBeforeCrmContactDelete',
'handleBeforeContactDelete'
);
}
/**
* Проверяет возможность удаления контакта.
*/
function handleBeforeContactDelete(int $contact_id): bool
{
global $APPLICATION;
$has_delete_access = true;
if (!$has_delete_access) {
$APPLICATION->ThrowException('Удаление контакта запрещено');
return false;
}
AddMessage2Log(
[
'message' => 'Проверка перед удалением контакта',
'contact_id' => $contact_id,
],
'contact_events'
);
return true;
}
registerBeforeContactDeleteHandler($event_manager);