CRM
Лиды
Работа с лидами CRM через PHP и фабрики: получение, добавление, изменение, удаление, статусы и события.
Лид — CRM-сущность с типом CCrmOwnerType::Lead. В отличие от сделки у лида
используется STATUS_ID, а не STAGE_ID.
PHP для коробки с подключённым ядром. Примеры чтения через фабрику рассчитаны на авторизованного пользователя и используют getItemsFilteredByPermissions. В CLI нужен отдельно заданный доверенный контекст. Примеры на странице самостоятельны: одинаковые вспомогательные функции не нужно объявлять вместе.
Основные операции
Базовая работа с лидами через фабрику CRM.
Получить лид
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
if (!Loader::includeModule('crm')) {
throw new \RuntimeException('Модуль crm не загружен');
}
global $USER;
if (!$USER || !$USER->IsAuthorized()) {
throw new \RuntimeException('Нужен авторизованный пользователь');
}
const CRM_LEAD_TYPE_ID = \CCrmOwnerType::Lead;
function fetchLeadFactory() {
return Service\Container::getInstance()->getFactory(CRM_LEAD_TYPE_ID);
}
function fetchLeadItem(int $lead_id) {
$factory = fetchLeadFactory();
if ($factory === null) {
return null;
}
return ($factory->getItemsFilteredByPermissions(['filter' => ['=ID' => $lead_id], 'limit' => 1])[0] ?? null);
}
$lead_item = fetchLeadItem($lead_id);
if ($lead_item !== null) {
$lead_data = $lead_item->toArray();
$title = $lead_item->getTitle();
$status_id = $lead_item->getStageId();
print_r($lead_data);
}
В новом API именованный метод getStageId() унифицирует работу со стадией
или статусом. Для лида фактическое поле в данных — STATUS_ID.
Получить список лидов
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const LEAD_LIMIT = 100;
if (!Loader::includeModule('crm')) {
throw new \RuntimeException('Модуль crm не загружен');
}
global $USER;
if (!$USER || !$USER->IsAuthorized()) {
throw new \RuntimeException('Нужен авторизованный пользователь');
}
const CRM_LEAD_TYPE_ID = \CCrmOwnerType::Lead;
function fetchLeadFactory() {
return Service\Container::getInstance()->getFactory(CRM_LEAD_TYPE_ID);
}
function fetchLeadItems(string $status_id): array {
$factory = fetchLeadFactory();
if ($factory === null) {
return [];
}
return $factory->getItemsFilteredByPermissions([
'select' => [
'ID',
'TITLE',
'STATUS_ID',
'NAME',
'LAST_NAME',
'COMPANY_TITLE',
'ASSIGNED_BY_ID',
'DATE_CREATE',
],
'filter' => [
'=STATUS_ID' => $status_id,
],
'order' => [
'ID' => 'ASC',
],
'limit' => LEAD_LIMIT,
]);
}
$lead_items = fetchLeadItems($status_id);
foreach ($lead_items as $lead_item) {
print_r($lead_item->toArray());
} Добавить лид
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
if (!Loader::includeModule('crm')) {
throw new \RuntimeException('Модуль crm не загружен');
}
global $USER;
if (!$USER || !$USER->IsAuthorized()) {
throw new \RuntimeException('Нужен авторизованный пользователь');
}
const CRM_LEAD_TYPE_ID = \CCrmOwnerType::Lead;
function fetchLeadFactory() {
return Service\Container::getInstance()->getFactory(CRM_LEAD_TYPE_ID);
}
function addLead(array $lead_fields): array {
$factory = fetchLeadFactory();
if ($factory === null) {
return [
'is_success' => false,
'lead_id' => 0,
'error_messages' => ['Фабрика лидов не найдена'],
];
}
$lead_item = $factory->createItem($lead_fields);
$operation = $factory->getAddOperation($lead_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'lead_id' => (int) $lead_item->getId(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$lead_fields = [
'TITLE' => $title,
'NAME' => $name,
'LAST_NAME' => $last_name,
'COMPANY_TITLE' => $company_title,
'STATUS_ID' => $status_id,
'SOURCE_ID' => $source_id,
'ASSIGNED_BY_ID' => $assigned_by_id,
];
$add_result = addLead($lead_fields);
print_r($add_result); Изменить лид
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
if (!Loader::includeModule('crm')) {
throw new \RuntimeException('Модуль crm не загружен');
}
global $USER;
if (!$USER || !$USER->IsAuthorized()) {
throw new \RuntimeException('Нужен авторизованный пользователь');
}
const CRM_LEAD_TYPE_ID = \CCrmOwnerType::Lead;
function fetchLeadFactory() {
return Service\Container::getInstance()->getFactory(CRM_LEAD_TYPE_ID);
}
function updateLeadStatus(int $lead_id, string $status_id): array {
$factory = fetchLeadFactory();
if ($factory === null) {
return [
'is_success' => false,
'error_messages' => ['Фабрика лидов не найдена'],
];
}
$lead_item = ($factory->getItemsFilteredByPermissions(['filter' => ['=ID' => $lead_id], 'limit' => 1])[0] ?? null);
if ($lead_item === null) {
return [
'is_success' => false,
'error_messages' => ['Лид не найден'],
];
}
$lead_item->set('STATUS_ID', $status_id);
$operation = $factory->getUpdateOperation($lead_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$update_result = updateLeadStatus($lead_id, $status_id);
print_r($update_result); Удалить лид
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
if (!Loader::includeModule('crm')) {
throw new \RuntimeException('Модуль crm не загружен');
}
global $USER;
if (!$USER || !$USER->IsAuthorized()) {
throw new \RuntimeException('Нужен авторизованный пользователь');
}
const CRM_LEAD_TYPE_ID = \CCrmOwnerType::Lead;
function fetchLeadFactory() {
return Service\Container::getInstance()->getFactory(CRM_LEAD_TYPE_ID);
}
function deleteLead(int $lead_id): array {
$factory = fetchLeadFactory();
if ($factory === null) {
return [
'is_success' => false,
'error_messages' => ['Фабрика лидов не найдена'],
];
}
$lead_item = ($factory->getItemsFilteredByPermissions(['filter' => ['=ID' => $lead_id], 'limit' => 1])[0] ?? null);
if ($lead_item === null) {
return [
'is_success' => false,
'error_messages' => ['Лид не найден'],
];
}
$operation = $factory->getDeleteOperation($lead_item);
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$delete_result = deleteLead($lead_id);
print_r($delete_result); События
События лидов позволяют выполнить свой PHP-код перед добавлением, после добавления, перед изменением, после изменения, перед удалением и после удаления лида.
Список событий
Обработчики обычно регистрируют в /local/php_interface/init.php или внутри
своего модуля. Для коробочной разработки это удобный способ реагировать на изменения
лидов без REST-приложения.
| Событие | Когда вызывается | Метод |
|---|---|---|
OnBeforeCrmLeadAdd | Перед добавлением лида. | CCrmLead::Add |
OnAfterCrmLeadAdd | После добавления лида. | CCrmLead::Add |
OnBeforeCrmLeadUpdate | Перед изменением лида. | CCrmLead::Update |
OnAfterCrmLeadUpdate | После изменения лида. | CCrmLead::Update |
OnBeforeCrmLeadDelete | Перед удалением лида. | CCrmLead::Delete |
OnAfterCrmLeadDelete | После удаления лида. | CCrmLead::Delete |
OnAfterExternalCrmLeadAdd | После добавления внешнего лида. | CCrmLead::Add |
OnAfterCrmLeadProductRowsSave | После сохранения товарных строк лида. | CCrmLead::SaveProductRows |
Перед добавлением
В OnBeforeCrmLeadAdd можно изменить поля до сохранения или отменить
создание лида. Например, можно заполнить источник по умолчанию или запретить создание
лида без названия.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
function registerBeforeLeadAddHandler(EventManager $event_manager): void {
$event_manager->addEventHandlerCompatible(
'crm',
'OnBeforeCrmLeadAdd',
'handleBeforeLeadAdd'
);
}
function handleBeforeLeadAdd(array &$lead_fields): bool {
global $APPLICATION;
if (empty($lead_fields['TITLE'])) {
$APPLICATION->ThrowException('Не заполнено название лида');
return false;
}
if (empty($lead_fields['SOURCE_ID'])) {
$lead_fields['SOURCE_ID'] = 'OTHER';
}
return true;
}
registerBeforeLeadAddHandler($event_manager);
В событиях до сохранения массив полей передаётся по ссылке. Если изменить значение в
$lead_fields, оно попадёт в сохраняемый лид.
После изменения
OnAfterCrmLeadUpdate можно использовать для логирования, синхронизации со
своими таблицами или запуска вспомогательной логики после изменения лида.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
function registerAfterLeadUpdateHandler(EventManager $event_manager): void {
$event_manager->addEventHandlerCompatible(
'crm',
'OnAfterCrmLeadUpdate',
'handleAfterLeadUpdate'
);
}
function handleAfterLeadUpdate(array &$lead_fields): void {
$lead_id = isset($lead_fields['ID']) ? (int) $lead_fields['ID'] : 0;
if ($lead_id <= 0) {
return;
}
AddMessage2Log(
[
'message' => 'Лид изменён',
'lead_id' => $lead_id,
'field_names' => array_keys($lead_fields),
],
'lead_events'
);
}
registerAfterLeadUpdateHandler($event_manager);
Событие после изменения не всегда содержит полный набор полей лида. Если нужно
проверить поле, которого нет в $lead_fields, лучше отдельно получить лид по
ID.
Перед удалением
OnBeforeCrmLeadDelete можно использовать, если удаление нужно проверить или
запретить.
<?php
use Bitrix\Main\EventManager;
$event_manager = EventManager::getInstance();
function registerBeforeLeadDeleteHandler(EventManager $event_manager): void {
$event_manager->addEventHandlerCompatible(
'crm',
'OnBeforeCrmLeadDelete',
'handleBeforeLeadDelete'
);
}
function handleBeforeLeadDelete(int $lead_id): bool {
global $APPLICATION;
$has_delete_access = true;
if (!$has_delete_access) {
$APPLICATION->ThrowException('Удаление лида запрещено');
return false;
}
AddMessage2Log(
[
'message' => 'Проверка перед удалением лида',
'lead_id' => $lead_id,
],
'lead_events'
);
return true;
}
registerBeforeLeadDeleteHandler($event_manager);