Выбор между send и sendImmediate для почтовых событий
При отправке почтовых событий в 1С-Битрикс разработчики часто используют старый API CEvent::Send(), не зная о современном классе Bitrix\Main\Mail\Event и его двух принципиально разных методах отправки. Неправильный выбор метода приводит к блокировке выполнения скрипта при проблемах с почтовым сервером или избыточной нагрузке на базу данных.
Метод send(): отложенная отправка
Метод send() добавляет событие в очередь отправки (таблица b_event). Агент Битрикс обработает событие позже:
use Bitrix\Main\Mail\Event;
// Добавление в очередь с автоматическим выбором шаблона
$result = Event::send([
'EVENT_NAME' => 'ORDER_CONFIRM',
'LID' => 's1',
'C_FIELDS' => [
'ORDER_ID' => $orderId,
'USER_EMAIL' => $email,
'ORDER_LIST' => $orderHtml,
],
]);
// Проверка результата
if ($result->isSuccess()) {
$eventId = $result->getId();
} else {
$errors = $result->getErrorMessages();
}
Метод send() возвращает объект Result с методами проверки успешности и получения ошибок, что упрощает обработку по сравнению со старым API.
Отправка конкретного почтового шаблона
Для отправки определённого шаблона используйте параметр MESSAGE_ID:
// Отправка конкретного шаблона (ID из таблицы b_event_message)
$result = Event::send([
'EVENT_NAME' => 'ORDER_CONFIRM',
'LID' => 's1',
'MESSAGE_ID' => 5, // ID конкретного шаблона
'C_FIELDS' => [
'ORDER_ID' => $orderId,
'USER_EMAIL' => $email,
],
]);
Без MESSAGE_ID система выберет все активные шаблоны по EVENT_NAME и LID. С MESSAGE_ID будет использован только указанный шаблон, даже если есть другие для этого типа события.
Метод sendImmediate(): немедленная отправка
Метод sendImmediate() отправляет письмо синхронно, минуя очередь:
use Bitrix\Main\Mail\Event;
// Немедленная отправка с конкретным шаблоном
$sendResult = Event::sendImmediate([
'EVENT_NAME' => 'CRITICAL_ALERT',
'LID' => 's1',
'MESSAGE_ID' => 12, // Опционально: конкретный шаблон
'C_FIELDS' => [
'MESSAGE' => 'Критическая ошибка в системе',
'TIME' => date('Y-m-d H:i:s'),
],
]);
// Результат - строковая константа
if ($sendResult === Event::SEND_RESULT_SUCCESS) {
// Отправлено успешно
} elseif ($sendResult === Event::SEND_RESULT_ERROR) {
// Ошибка отправки
} elseif ($sendResult === Event::SEND_RESULT_TEMPLATE_NOT_FOUND) {
// Шаблон не найден
}
Используйте sendImmediate() для критических уведомлений в фоновых задачах (агенты, cron), когда письмо должно уйти немедленно без сохранения в очередь.
Метод sendImmediate() возвращает строку, в отличие от send(), а не объект Result.
Обработка вложений
Оба метода поддерживают массив вложений в параметре FILE:
$result = Event::send([
'EVENT_NAME' => 'DOCUMENT_READY',
'LID' => ['s1', 's2'], // Множественные сайты
'C_FIELDS' => ['DOC_NUMBER' => '123'],
'FILE' => [
456, // ID из b_file (не копируется)
'/path/to/new.pdf', // Новый файл (будет скопирован)
],
]);
Система автоматически определяет тип вложения: числовые значения считаются ID файлов, строки - путями к файлам для копирования.
Итог
Используйте send() для пользовательских сценариев и sendImmediate() для фоновых задач. Параметр MESSAGE_ID позволяет точно контролировать, какой шаблон будет использован.
Похожие советы
Настройка OpenSearch для полнотекстового поиска в Битрикс
Стандартный поиск Битрикс использует таблицы MySQL для хранения поискового индекса. На проектах с большим объёмом контента это приводит к медленным запросам и высокой нагрузке на базу данных. Начиная с версии 25.0 модуля поиска, Битрикс поддерживает OpenSearch (форк Elasticsearch) — полнотекстовый поисковый движок с морфологией и горизонтальным масштабированием.
Настройка через административный раздел
Подключение OpenSearch выполняется в настройках модуля «Поиск» без написания кода:
- Перейдите в раздел Настройки → Настройки продукта → Настройки модулей → Поиск
- Откройте вкладку Морфология
- В поле Полнотекстовый поиск с помощью выберите OpenSearch
- Заполните параметры подключения:
- Сервер OpenSearch — адрес в формате
https://host:9200 - Пользователь — имя пользователя для авторизации
- Пароль — пароль пользователя
- Название индекса — произвольное имя (латиница, цифры, дефис, подчёркивание)
- Сервер OpenSearch — адрес в формате
- Для каждого сайта выберите Анализатор поисковых запросов (russian, english и др.)
- Сохраните настройки
После сохранения система проверит подключение. При успешном соединении появится уведомление о необходимости переиндексации.

Переиндексация контента
После смены поискового движка выполните полную переиндексацию:
- Перейдите в Настройки → Поиск → Переиндексация
- Установите флаг Очистить индекс
- Нажмите Начать и дождитесь завершения
Все существующие данные будут перенесены в OpenSearch. Новый контент индексируется автоматически.

Как это работает
После настройки класс CSearchFullText::getInstance() автоматически возвращает экземпляр CSearchOpenSearch вместо стандартного движка. Все компоненты поиска (bitrix:search.page, bitrix:search.title) начинают работать через OpenSearch без изменения кода.
Система создаёт отдельный индекс для каждого сайта с суффиксом: {index_name}-{site_id}. Шаблоны индексов обновляются автоматически при изменении версии модуля.
Поддерживаемые языковые анализаторы
OpenSearch поддерживает морфологический анализ для 30 языков. Основные:
| Анализатор | Язык |
|---|---|
| russian | Русский |
| english | Английский |
| german | Немецкий |
| french | Французский |
| spanish | Испанский |
Преимущества OpenSearch
- Быстрый полнотекстовый поиск на больших объёмах данных
- Встроенная морфология для множества языков
- Горизонтальное масштабирование через кластеризацию
- Снижение нагрузки на основную базу данных
- Релевантное ранжирование результатов
Переход на OpenSearch рекомендуется для проектов с количеством индексируемых документов свыше 50 000 или при высокой частоте поисковых запросов.
Параллельные HTTP-запросы через асинхронный API HttpClient
При интеграции с внешними сервисами часто требуется выполнить несколько HTTP-запросов. Последовательное выполнение приводит к суммированию времени ожидания каждого запроса. Если три API отвечают по 500мс, общее время составит 1.5 секунды. Класс Bitrix\Main\Web\HttpClient поддерживает асинхронное выполнение запросов через curl_multi, что позволяет выполнять их параллельно.
Для асинхронных запросов используется метод sendAsyncRequest(), который возвращает объект Promise. Promise реализует интерфейс Http\Promise\Promise и поддерживает цепочки обработчиков через метод then().
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Uri;
// Важно: для асинхронных запросов требуется CURL
$client = new HttpClient(['useCurl' => true]);
// Список URL для параллельных запросов
$urls = [
'products' => 'https://api.example.com/products',
'categories' => 'https://api.example.com/categories',
'prices' => 'https://api.example.com/prices',
];
$promises = [];
foreach ($urls as $key => $url)
{
// Создаём PSR-7 совместимый Request
$request = new Request('GET', new Uri($url));
// sendAsyncRequest() не блокирует выполнение
$promises[$key] = $client->sendAsyncRequest($request);
}
// wait() блокирует до завершения всех запросов
$responses = $client->wait();
// Обрабатываем результаты
foreach ($promises as $key => $promise)
{
try
{
// wait() на конкретном promise возвращает Response
$response = $promise->wait();
$data[$key] = json_decode((string)$response->getBody(), true);
}
catch (\Bitrix\Main\Web\Http\ClientException $e)
{
// Обработка ошибок сети
$data[$key] = ['error' => $e->getMessage()];
}
}
Promise поддерживает callback-функции для обработки успешных и неуспешных запросов:
$promise = $client->sendAsyncRequest($request);
// Регистрируем обработчики до вызова wait()
$promise->then(
function ($response) {
// Вызывается при успешном ответе
// Можно модифицировать и вернуть response
return $response;
},
function ($exception) {
// Вызывается при ошибке
// Логируем или обрабатываем исключение
return $exception;
}
);
// Запускаем выполнение
$client->wait();
Для POST-запросов с телом используйте Http\FormStream:
use Bitrix\Main\Web\Http\FormStream;
$body = new FormStream(['param1' => 'value1', 'param2' => 'value2']);
$request = new Request('POST', new Uri($url), ['Content-Type' => 'application/x-www-form-urlencoded'], $body);
$promise = $client->sendAsyncRequest($request);
Асинхронный API HttpClient использует curl_multi_exec() под капотом, что обеспечивает истинную параллельность на уровне сетевых операций. Три запроса по 500мс выполнятся примерно за 500мс вместо 1.5 секунд.
Безопасная работа с JSON через Bitrix\Main\Web\Json
Проблема
При работе с JSON в 1С-Битрикс многие разработчики используют нативные функции json_encode() и json_decode() без должной обработки ошибок. Это приводит к silent-ошибкам: когда данные не кодируются корректно, функция возвращает false или null, но код продолжает выполняться. В результате возникают сложно диагностируемые проблемы с невалидными данными.
Решение
Класс Bitrix\Main\Web\Json предоставляет безопасные методы для работы с JSON, автоматически выбрасывая исключения при ошибках кодирования/декодирования.
Базовое использование
use Bitrix\Main\Web\Json;
use Bitrix\Main\ArgumentException;
// Безопасное кодирование
try {
$jsonString = Json::encode($data);
} catch (ArgumentException $e) {
// Обработка ошибки кодирования
}
// Безопасное декодирование
try {
$array = Json::decode($jsonString);
} catch (ArgumentException $e) {
// Обработка ошибки декодирования
}
Преимущества класса
Класс автоматически использует оптимальные опции по умолчанию:
JSON_HEX_TAG,JSON_HEX_AMP,JSON_HEX_APOS,JSON_HEX_QUOT— защита от XSSJSON_UNESCAPED_UNICODE— корректная работа с кириллицейJSON_INVALID_UTF8_SUBSTITUTE— замена невалидных символов UTF-8JSON_THROW_ON_ERROR— автоматический выброс исключений
Валидация JSON
Класс предоставляет метод для проверки валидности JSON-строки:
use Bitrix\Main\Web\Json;
use Bitrix\Main\Application;
$request = Application::getInstance()->getContext()->getRequest();
$jsonString = $request->getPost('json_data') ?? '';
if (!Json::validate($jsonString)) {
throw new \Bitrix\Main\ArgumentException(
"Невалидный JSON в параметре json_data"
);
}
$data = Json::decode($jsonString);
Кастомные опции кодирования
Вы можете переопределить опции при необходимости:
use Bitrix\Main\Web\Json;
// Форматированный вывод с отступами
$prettyJson = Json::encode(
$data,
Json::DEFAULT_OPTIONS | JSON_PRETTY_PRINT
);
// Без экранирования слешей для URL
$jsonForApi = Json::encode(
['url' => 'https://example.com/path'],
Json::DEFAULT_OPTIONS | JSON_UNESCAPED_SLASHES
);
Итог
Использование Bitrix\Main\Web\Json вместо нативных функций обеспечивает явную обработку ошибок и автоматическую защиту от XSS. Метод validate() позволяет безопасно проверять пользовательский ввод перед декодированием.