#Когда возникает проблема и как её отличить
Кириллица может искажаться после миграции на PHP 8, если приложение смешивает Windows-1251 и UTF-8 либо полагается на неявную кодировку функций mbstring. Сам факт обновления PHP не конвертирует старые файлы и базу данных.
#Возможные причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Строки содержат байты Windows-1251Кодировка файла/БД отличается от ожидаемой UTF-8. | Вместо текста видны «кракозябры», особенно после обновления шаблонов | Определить исходную кодировку и конвертировать в копии. |
| Неявная кодировка mbstringФункция работает с иной кодировкой, чем входные данные. | mb_strlen или mb_substr дают неверное число символов | Передать параметр кодировки явно или настроить согласованную среду. |
| Не совпадают заголовки HTTP и данныеContent-Type charset и фактические байты отличаются. | Браузер показывает текст неверно при правильном PHP-коде | Согласовать UTF-8 от источника до HTML. |
#Пошаговая диагностика и исправление
- Сохраните оригинальные данные до преобразованияСоздайте копию файлов и базы в исходной кодировке. Не открывайте и не сохраняйте все PHP-файлы вслепую в UTF-8: автоматическая перекодировка уже повреждённого текста может усугубить ситуацию. Выберите одну короткую строку, кодировка которой достоверно известна, и воспроизведите проблему на тестовой копии.
- Определите слой, на котором портится текстОткройте HTML-ответ в инструментах разработчика браузера → вкладка Network/«Сеть», выберите запрос и проверьте
Content-Typeиcharset. Сравните исходные байты в файле, результат SQL и то, что передано в ответе. Если строка уже неправильная в базе, правка HTTP-заголовка сама по себе не исправит данные. - Уточните реальную внутреннюю кодировку mbstringВ закрытом тестовом PHP-файле выполните
mb_internal_encoding()иini_get("default_charset"), чтобы увидеть соответствующие значения. Проверьте, включён ли модульmbstringименно в веб-PHP. Не считайте настройки консольногоphp -iдостаточными: PHP-FPM может иметь другую конфигурацию. - Укажите кодировку при обработке строкДля заведомо корректной UTF-8-строки используйте
mb_strlen($text, "UTF-8")илиmb_substr($text, 0, 20, "UTF-8"). Если поступают байты Windows-1251, сначала отдельно преобразуйте их с явно указанной исходной кодировкой, напримерmb_convert_encoding($text, "UTF-8", "Windows-1251"), но только после подтверждения источника, а не на каждом запросе без проверки. - Согласуйте файл, базу, ответ и HTMLСохраните шаблоны как UTF-8 без потери исходных символов. Для веб-ответа укажите
Content-Type: text/html; charset=UTF-8на нужном уровне, а в HTML —<meta charset="UTF-8">. При работе с MySQL проверьте кодировку соединения, таблиц и полей отдельно; не выполняйте массовый ALTER TABLE без резервной копии и анализа данных. - Проверьте кириллицу и смешанные символыНа тестовом сайте отобразите проверочную строку «Ёж, Москва, 123» и строку с латиницей. Проверьте длину через
mb_strlen, сохранение и повторное чтение из базы. Если дефект сохраняется лишь у старых записей, установите, где уже произошло двойное преобразование; вернитесь к исходной копии и исправляйте один слой за раз.
#Как проверить, что проблема устранена
В браузере и после чтения из базы должны совпадать исходная кириллица, длина строки и последовательность символов. При оставшихся «кракозябрах» ищите неверную кодировку на конкретном переходе данных, а не меняйте все настройки одновременно.
#Если ошибка осталась
Повторите исходный сценарий в тестовой среде, откройте свежую запись журнала с точным временем, именем функции, файлом и строкой. Сравните новое сообщение с исходным: ошибка могла переместиться на следующий участок кода. Не подавляйте все ошибки общим обработчиком. Если изменения затрагивали работающий проект, восстановите сохранённую копию и разберите новое сообщение до повторного переноса.