Эта статья для тех, кто хочет перекодировать свой сайт в кодировку UTF-8. Постараюсь в подробностях рассказать о деталях и шагах перехода к другой кодировке.
Я всегда писал сайты, используя кодировку cp1251, это было вызвано несколькими причинами:
- Сайты только для русскоязычного сегмента;
- PHP 4-5 хорошо работает с однобайтовыми кодировками.
Не так давно решил пересесть на UTF-8, поэтому расскажу о стадиях перехода и нужно ли это делать сейчас.
1. Качаем любой текстовый редактор, который имеет функцию перекодировки в UTF-8 без BOM.
Я для этого использую Notepad++, кстати, на данный момент это моя основная IDE. Перекодировать открытый документ можно так: Меню «Кодировка» -> Преобразовать в UTF-8 без BOM.
Почему без BOM? Byte Order Mark это метка порядка байтов Юникода, которая добавляется в начало документа. Нам эта метка не нужна по ряду причин:
- PHP скрипт не запуститься;
- Обычно сайт собирается из нескольких шаблонов, а метка должна быть только в начале документа. Это значит, что другие метки будут отображаться на экране.
2. Настройка Apache и (или) Nginx.
Нам нужно заставить веб-сервера отдавать клиенту нужную кодировку.
В конфиге Apache или в файле htaccess устанавливаем AddDefaultCharset UTF-8.
В конфиге Nginx находим и изменяем значение директивы charset на utf-8;
На самом деле это идеалистический метод, можно и просто отдавать заголовок из PHP
header(‘Content-Type: text/html; charset=utf-8’);
3. Локаль сервера
Нам нужна локаль ru_RU.UTF-8. Конечно, её можно установить с помощью PHP функции setlocale(LC_ALL, ‘ru_RU.utf8’), но это только в том случае, если нужная локаль присутствует в системе.
Работу с локалью описывать не буду, но вы можете почитать эту статью.
4. Делаем дамп базы данных и преобразуем в UTF-8 без BOM.
Для этого воспользуемся любым дампером. Я использовал Sypex Dumper. Есть Free версия, и работает достаточно быстро.
Вообщем делаем дамп, открываем его в Notepad++ и преобразуем в UTF-8 без BOM. Так же меняем DEFAULT CHARSET=cp1251 на DEFAULT CHARSET=utf8. И cp1251_general_ci на utf8_general_ci везде где это нужно.
Создам новую базу данных со сравнением utf8_general_ci и заливаем в ней дамп.
5. Перекодируем все файла сайта в UTF-8 без BOM.
Нудное занятие, открываем файлы в Notepad++ и преобразуем в UTF-8 без BOM. Шаблоны, PHP, CSS и JS.
6. Соединение с базой данных
Не забываем про кодировку соединения с базой данных. Если вы используете MySQL, то можно просто сразу после соединения отдать запросом SET NAMES ‘utf8’
7. PHP и работа со стоками
А тут у нас самое весёлое. Все стандартные стоковые функции PHP работают только с однобайтовыми кодировками. Так что забываем про substr, strlen, strtoupper, strpos, str_replace и все другие.
Что же делать? Пользуемся аналогами из пакета mbstring который специально предназначен для работы со стоками в многобайтовых кодировках.
mb_internal_encoding(UTF-8); mb_strlen('строка');
Или
mb_strlen('строка', 'UTF-8');
Или устанавливаем директиву mbstring.internal_encoding = UTF-8 в php.ini
mb_strlen('строка');
К сожалению, аналоги функций есть далеко не все. Остальные функции придётся писать самому, например, такие как mb_ucfirst.
В функции htmlspecialchars нужно постоянно указывать третий параметр:
htmlspecialchars($srt, ENT_QUOTES, 'UTF-8');
Не работает доступ к символу в строке: $srt[0] или $srt{0}. Теперь нужно использовать функцию mb_strcut, которая является аналогом substr.
Не верно работаю регулярные выражения preg_*. Что бы заставить эти функции работать с юникодом, нужно указывать модификатор «u».
echo preg_replace('#[абв]+#u', '', 'ааавкккббввбббппп'); // не работает без модификатора u
Русские буквы теперь не считаются буквами:
if(preg_match('#[\w]#ui', 'ааавкккббввбббппп')) echo "Да это буква"; // пусто
Буква «ё» не входит в диапазон русских букв:
if(preg_match('#[а-я]#ui', 'ёёёЁёё')) echo "Тут есть буква Ё"; // пусто
Это можно побороть так:
if(preg_match('#[а-яё]#ui', 'ёёёЁёё')) echo "Тут есть буква Ё";
Возможно это не всё, и есть что-то ещё. Радует только то, что функции сортировки вроде работают нормально.