Перейти к содержанию

Работа с эмодзи

В MySQL кодировка utf8_general_ci поддерживает максимум три байта на символ. Эмодзи занимают четыре байта.

При сохранении четырехбайтного символа в базу данных:

  • запись прерывается на символе эмодзи,

  • весь последующий текст теряется,

  • система возвращает ошибку записи.

Конвертация базы данных в utf8mb4_general_ci изменяет структуру таблиц и индексов. Ее не выполняют на работающих проектах.

Для решения задачи используйте класс \Bitrix\Main\Text\Emoji. Он преобразует эмодзи в безопасный формат перед сохранением и восстанавливает исходные символы при чтении. Это позволяет полноценно работать с эмодзи без изменения кодировки базы данных.

Как работает преобразование

Класс \Bitrix\Main\Text\Emoji заменяет четырехбайтные символы на текстовое представление в формате :код:. Каждый байт кодируется двумя шестнадцатеричными символами, поэтому код содержит ровно восемь символов.

  • при сохранении: 😊 -> :0001f60a:,

  • при чтении: :0001f60a: -> 😊.

Класс обрабатывает все четырехбайтные символы: эмодзи, иероглифы и специальные символы. Если последовательность вида :код: не соответствует эмодзи, она остается без изменений. Текст без четырехбайтных символов не изменяется.

Настроить обработку эмодзи в ORM

ORM позволяет работать с таблицами базы данных через классы-модели. Для автоматической обработки эмодзи укажите функции обратного вызова в описании полей модели.

Используйте два параметра:

  • save_data_modification — вызывает функцию \Bitrix\Main\Text\Emoji::encode перед записью данных в базу,

  • fetch_data_modification — вызывает функцию \Bitrix\Main\Text\Emoji::decode при чтении данных из базы.

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Text\Emoji;

return [
    'TITLE' => [
        'data_type' => 'string',
        'validation' => [static::class, 'validateTitle'],
        'title' => Loc::getMessage('CHAT_ENTITY_TITLE_FIELD'),
        'save_data_modification' => [Emoji::class, 'getSaveModificator'],
        'fetch_data_modification' => [Emoji::class, 'getFetchModificator'],
    ],
];

Параметры save_data_modification и fetch_data_modification настраиваются один раз в описании полей. После этого не вызывайте методы \Bitrix\Main\Text\Emoji::encode и \Bitrix\Main\Text\Emoji::decode вручную — преобразование выполняется автоматически.

Сохранить эмодзи без ORM

При прямой работе с базой данных преобразуйте текст перед сохранением.

use Bitrix\Main\Application;
use Bitrix\Main\Text\Emoji;

$request = Application::getInstance()->getContext()->getRequest();

$text = (string)$request->getPost('comment');
$encodedText = Emoji::encode($text);

// Сохраните $encodedText в базу данных

Метод encode заменяет каждый четырехбайтный символ на шестнадцатеричное представление в формате :код:. Результат безопасен для записи в кодировку utf8_general_ci.

Восстановить эмодзи при выборке

После получения текста из базы данных преобразуйте его обратно в читаемый вид.

// При подготовке данных для вывода в шаблон
use Bitrix\Main\Text\Emoji;

/** @var array $result */
$dbText = (string)($result['COMMENT'] ?? '');
$decodedText = Emoji::decode($dbText);
// Используйте $decodedText в шаблоне

Метод decode ищет последовательности вида :код:, проверяет их валидность по паттерну эмодзи и заменяет на исходный символ. Невалидные последовательности остаются без изменений.

Использовать CTextParser

CTextParser — встроенный класс Bitrix Framework для безопасного вывода и обработки текста в шаблонах. Если в проекте настроен CTextParser с обработкой эмодзи, дополнительный вызов decode не требуется. Проверьте конфигурацию парсера в вашем проекте.

// В компоненте при подготовке данных для шаблона
$parser = new \CTextParser();

$textFromDatabase = (string)$textFromDatabase;
$result = $parser->convertText($textFromDatabase);
// $result содержит текст с корректно отображаемыми эмодзи

Проверить работу решения

Выполните проверку в четыре шага.

  1. Сохраните текст с эмодзи через настроенный метод: с encode или ORM.

  2. Откройте запись в базе данных и убедитесь, что эмодзи представлены как :код:.

  3. Выведите текст на страницу сайта.

  4. Проверьте, что эмодзи отображаются корректно и текст после них не обрезан.