Заметки
Пустое значение поля в CRM может быть не null
Почему пустое поле CRM в Bitrix24 не всегда стоит проверять только через null.
В CRM-полях Bitrix24 пустое значение не всегда приходит как null.
Перед проверками лучше привести значение к понятному внутреннему состоянию.
Суть проблемы
В коде легко написать проверку только на null, а потом получить ошибку в логике,
потому что поле пришло пустой строкой, нулём или вообще отсутствует в массиве.
Коротко
Пустое значение CRM-поля лучше не проверять одной универсальной проверкой.
В зависимости от типа поля, способа получения данных и конкретного API можно встретить разные варианты пустоты:
null;- пустая строка
''; - строка
'0'; - число
0; - пустой массив;
- отсутствующий ключ в массиве.
Из-за этого проверки вроде $value === null или empty($value)
могут дать не тот результат.
Где встречается
Чаще всего это всплывает при работе с пользовательскими полями CRM:
- в сделках;
- в лидах;
- в контактах и компаниях;
- в смарт-процессах;
- в обработчиках событий CRM;
- в фильтрах для выборки сущностей;
- при сравнении старого и нового значения поля.
Отдельно стоит быть внимательным с полями типа Да/Нет. В рабочей логике такое поле
удобнее воспринимать не как простой bool, а как состояние.
Проверка значений
Надёжнее сначала привести значение к своему формату, а уже потом использовать его в условиях.
Не проверять только на null
Проверка только на null слишком узкая. Она не поймает пустую строку и отсутствующий
ключ, если значение берётся из массива CRM-полей.
<?php
$field_value = $deal_data['UF_CRM_EXAMPLE_FIELD'] ?? null;
if ($field_value === null) {
// Сработает только для null или отсутствующего ключа.
}
Проверка через empty() тоже не всегда подходит, потому что для PHP значения
0 и '0' тоже считаются пустыми.
<?php
$field_value = $deal_data['UF_CRM_EXAMPLE_FIELD'] ?? null;
if (empty($field_value)) {
// Сюда попадут null, '', 0, '0', false и пустой массив.
} Поле Да/Нет
У поля типа Да/Нет в прикладной логике может быть три состояния:
- значение не заполнено;
- выбрано «Да»;
- выбрано «Нет».
Поэтому его лучше не проверять как обычный true или false.
Иначе можно случайно смешать «Нет» и «не заполнено».
<?php
$field_value = $deal_data['UF_CRM_EXAMPLE_BOOLEAN'] ?? null;
if ($field_value) {
// Так лучше не делать для CRM-поля Да/Нет.
} Безопаснее явно определить, что для текущей задачи считается «Да», что считается «Нет», а что считается незаполненным значением.
Пример нормализации
Пример ниже не привязан к конкретному порталу. Он показывает общий подход: получить значение поля, нормализовать его и дальше работать уже с понятными состояниями.
<?php
use Bitrix\Main\Loader;
const CRM_MODULE_ID = 'crm';
const DEAL_ID = 0;
const YES_NO_FIELD = 'UF_CRM_EXAMPLE_BOOLEAN';
const VALUE_EMPTY = 'empty';
const VALUE_YES = 'yes';
const VALUE_NO = 'no';
Loader::includeModule(CRM_MODULE_ID);
$deal_data = fetchDealData(DEAL_ID);
$field_value = $deal_data[YES_NO_FIELD] ?? null;
$field_state = normalizeYesNoValue($field_value);
if ($field_state === VALUE_EMPTY) {
// Поле не заполнено.
}
if ($field_state === VALUE_YES) {
// Выбрано Да.
}
if ($field_state === VALUE_NO) {
// Выбрано Нет.
}
/**
* Получает данные сделки.
*/
function fetchDealData(int $deal_id): array
{
if ($deal_id <= 0) {
return [];
}
$deal_result = CCrmDeal::GetListEx(
[],
['ID' => $deal_id],
false,
false,
['ID', YES_NO_FIELD]
);
$deal_data = $deal_result ? $deal_result->Fetch() : false;
return is_array($deal_data) ? $deal_data : [];
}
/**
* Приводит значение поля Да/Нет к внутреннему состоянию.
*/
function normalizeYesNoValue(mixed $field_value): string
{
if ($field_value === null || $field_value === '') {
return VALUE_EMPTY;
}
if ($field_value === true || $field_value === 1 || $field_value === '1' || $field_value === 'Y') {
return VALUE_YES;
}
if ($field_value === false || $field_value === 0 || $field_value === '0' || $field_value === 'N') {
return VALUE_NO;
}
return VALUE_EMPTY;
} Главная идея — не раскидывать проверки по всему коду, а один раз привести значение к понятному формату и дальше сравнивать уже его.