← Назад к заметкам

Заметки

Пустое значение поля в CRM может быть не null

Почему пустое поле CRM в Bitrix24 не стоит проверять только через null.

Пустое CRM-поле не всегда приходит как null. В коде лучше явно решить, какие значения считать пустыми, а какие — осознанно заполненными.

Проблема

В CRM-полях Bitrix24 пустота может выглядеть по-разному. Иногда это null, иногда пустая строка, 0, '0', пустой массив или вообще отсутствующий ключ в массиве.

Если проверять поле только через $value === null, часть пустых значений можно пропустить. Если проверять через empty(), можно случайно смешать пустоту и нормальное значение вроде 0.

Чаще всего в CRM-данных можно встретить такие варианты:

  • null;
  • пустая строка '';
  • строка '0';
  • число 0;
  • пустой массив;
  • отсутствующий ключ в массиве.

Поэтому перед условиями лучше привести значение к понятному внутреннему состоянию: пусто, да, нет, выбрано, не выбрано и так далее.

Проверка значений

Надёжнее не пытаться одной проверкой закрыть все типы полей, а отдельно описывать правила для конкретного поля и конкретной задачи.

Проверка только на null слишком узкая. Она не поймает пустую строку, если поле пришло из CRM именно так.

<?php

$field_value = $deal_data['UF_CRM_EXAMPLE_FIELD'] ?? null;

if ($field_value === null) {
    // Сработает только для null или отсутствующего ключа.
}

empty() тоже не всегда подходит. В PHP значения 0 и '0' считаются пустыми, хотя для CRM-поля это может быть осмысленное значение.

<?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;
}

Такой подход удобен тем, что вся спорная логика остаётся в одной функции. Дальше по коду уже не нужно каждый раз вспоминать, что именно пришло из CRM: null, пустая строка, 0 или 'N'.