Русский текст и UTF-8 в PHP: настройка функций регистра и кодировки

Раздел: Стандартные функции -> Регистр и кодировка

Работа с русскими символами в PHP (кодировка UTF-8)

При обработке текстов на кириллице в PHP необходимо учитывать, что стандартные строковые функции (strlen, substr, strtolower и другие) ориентированы на однобайтовые кодировки. Для корректной работы с многобайтовыми символами, в частности русскими буквами в кодировке UTF-8, требуется использование специальных расширений. В этой статье рассматриваются основные подходы и их практические применения.

Основное решение: расширение mb_string (Multibyte String)

Набор функций mb_* предоставляет полноценную поддержку многобайтовых кодировок. Главное преимущество - все операции выполняются с учётом кодировки, заданной через mb_internal_encoding или передаваемой параметром. Это единственный способ гарантировать правильное поведение при работе с русским текстом.

Как правильно настроить PHP для работы с UTF-8 и русскими символами?


<?php
// Устанавливаем внутреннюю кодировку UTF-8
mb_internal_encoding('UTF-8');

// Теперь функции mb_* будут использовать UTF-8 по умолчанию
$text = 'Привет, мир!';
echo mb_strlen($text); // 13 (количество символов)
echo strlen($text);    // 19 (количество байт)
?>
  

Php русские символы (работа с русскими символами в php (кодировка utf-8))

Установка кодировки через mb_internal_encoding или параметр encoding в каждом вызове обязательна. Без этого mb_strlen может вернуть неверное значение.

Типичные ошибки:

  • Забыли установить внутреннюю кодировку - функции mb_* используют ISO-8859-1, что приводит к разбиению русских букв на байты.
  • Смешивание mb_* и обычных функций на одной строке - например, substr после mb_strlen даёт некорректный результат.
  • Отсутствие расширения mb_string на сервере - необходимо установить или использовать альтернативы.

Цель: обработка строк любой длины и регистра, безопасное обрезание, поиск, замена. Используется в CMS, форумах, системах управления контентом.

Как работать с русскими строками, если расширение mb_string недоступно?

Расширение iconv предоставляет функции iconv_strlen, iconv_substr, iconv_strpos. Они также корректно обрабатывают многобайтовые строки, но имеют ограниченный функционал (нет mb_strtolower и т.д.).


<?php
$text = 'Здравствуйте!';
echo iconv_strlen($text, 'UTF-8'); // 13
echo iconv_substr($text, 0, 6, 'UTF-8'); // Здравс
?>
  

Проблемы iconv: на разных системах возможны расхождения в обработке невалидных последовательностей; отсутствие функций для перевода регистра. Для приведения регистра придётся использовать mb_convert_case из mb_string или писать собственную таблицу преобразования.

Цель: лёгкая альтернатива при базовых операциях, когда mb_string не установлено.

Как искать русские символы с помощью регулярных выражений?

Модификатор u в регулярных выражениях включает режим UTF-8. Это позволяет корректно сопоставлять кириллические классы, например [а-яё].


<?php
$text = 'Ёлка и яблоко';
// Поиск всех русских букв
preg_match_all('/[а-яё]/iu', $text, $matches);
print_r($matches[0]);
?>
  

Результат содержит каждую букву отдельно. Без модификатора u символы ё и другие могут не распознаваться.

Ошибки: забывают модификатор u - тогда и (байты) считаются за символы; неправильно составленный диапазон [а-я] не включает букву ё, нужно явно добавлять [а-яё] или использовать свойство \p{Cyrillic}.

Цель: валидация ввода, замена подстрок, разбор текста.

Как безопасно сравнивать русские строки без учёта регистра?

Функция strcasecmp работает с байтами и не учитывает многобайтовость. Для корректного сравнения нужно перевести обе строки в один регистр через mb_strtolower и сравнить через ===.


<?php
$str1 = 'Привет';
$str2 = 'ПРИВЕТ';
if (mb_strtolower($str1) === mb_strtolower($str2)) {
    echo 'Строки равны';
}
?>
  

Типичная ошибка: использование strcasecmp напрямую - для русских символов он сравнивает байты, поэтому 'А' и 'а' (разные байты) будут признаны неравными. Кроме того, нужно учитывать locale - mb_strtolower использует кодировку, но не локаль, поэтому проблем не возникает.

Цель: поиск, сортировка, проверка совпадений.

Как преобразовывать кодировку текста из одной в другую (например, CP1251 в UTF-8)?

Функция mb_convert_encoding (или iconv) позволяет перекодировать строки. Это часто требуется при импорте данных из старых систем.


<?php
$cp1251 = file_get_contents('old.txt'); // файл в Windows-1251
$utf8 = mb_convert_encoding($cp1251, 'UTF-8', 'CP1251');
file_put_contents('new.txt', $utf8);
?>
  

Проблемы: неверное указание исходной кодировки ведёт к кракозябрам; при наличии смешанной кодировки (часть строк уже UTF-8) лучше сначала определить её через mb_detect_encoding с порядком приоритетов.

Цель: интеграция унаследованных данных, работа с внешними API.

Расширенные примеры работы с русскими символами

Пример 1: поиск позиции подстроки с учётом UTF-8

Функция mb_strpos корректно находит первое вхождение подстроки, считая символы, а не байты. В отличие от strpos, которая для русских символов возвращает смещение в байтах.

Пример

<?php
mb_internal_encoding('UTF-8');
$text = 'Привет, как дела? Привет!';
$pos = mb_strpos($text, 'Привет');
echo 'Первое вхождение на позиции: ' . $pos; // 0
$pos2 = mb_strpos($text, 'Привет', 10);
echo 'Второе вхождение на позиции: ' . $pos2; // 17
?>
Первое вхождение на позиции: 0
Второе вхождение на позиции: 17

Если использовать strpos, для первого вхождения результат будет 0 (повезло), а для второго - 24 (байтовый сдвиг, не совпадает с символьным).

Пример 2: перевод регистра для всего текста с mb_convert_case

mb_convert_case позволяет установить разный тип преобразования: MB_CASE_UPPER, MB_CASE_LOWER, MB_CASE_TITLE (каждое слово с заглавной).

Пример

<?php
$text = 'привет, МИР! ёлка';
echo mb_convert_case($text, MB_CASE_TITLE, 'UTF-8'); // Привет, Мир! Ёлка
// Для сравнения strtoupper выдаст искажённый результат
?>
Привет, Мир! Ёлка

Обратите внимание, что буква 'ё' корректно преобразуется в 'Ё'. Обычная strtoupper этого не делает.

Пример 3: замена всех вхождений русских букв с регулярным выражением и модификатором u

Использование preg_replace с модификатором u для замены всех гласных на звёздочки.

Пример

<?php
$text = 'Привет, как дела?';
$pattern = '/[аеёиоуыэюя]/iu';
$replaced = preg_replace($pattern, '*', $text);
echo $replaced;
?>
Пр*в*т, к*к д*л*?

Без модификатора u замена прошла бы только по однобайтовым символам, что привело бы к повреждению UTF-8 последовательности.

Пример 4: работа с JSON и русскими строками

json_encode автоматически экранирует многобайтовые символы в \uXXXX, если не задать опцию JSON_UNESCAPED_UNICODE. Для хранения читаемого UTF-8 в JSON нужно её указать.

Пример

<?php
$data = ['name' => 'Иван', 'city' => 'Москва'];
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// vs стандартное поведение
?>
{"name":"Иван","city":"Москва"}

Без опции результат: {"name":"\u0418\u0432\u0430\u043d","city":"\u041c\u043e\u0441\u043a\u0432\u0430"}. Это менее читаемо, но занимает больше места. Проблема возникает при декодировании, если кодировка исходной строки не UTF-8 - json_decode может вернуть null или искажённые данные.

Работа с русскими символами в PHP (кодировка UTF-8) - comments

En
Php русские символы (php)