Строка PHP - это просто последовательность байтов, без какой-либо кодировки. Строковые значения могут поступать из различных источников: клиента (через HTTP), базы данных, файла или из строковых литералов в вашем исходном коде. PHP читает все это как байтовые последовательности и никогда не извлекает никакой информации о кодировке.
Пока все ваши источники данных и места назначения используют одну и ту же кодировку, самое худшее, что может случиться, это неправильные позиции строк (если вы используете многобайтовые кодировки), поскольку PHP будет считать байты, а не символы.
Но если кодировки не совпадают (например, вы записываете строковый литерал в исходный файл, сохраненный как UTF-8, а затем отправляете его в базу данных, которая ожидает Latin-1), PHP не выполнит для вас никакого преобразования: счастливо скопировать байты по сырью.
Самое разумное решение:
- Установите внутреннюю кодировку PHP в UTF-8.
- Сохраните все ваши исходные файлы как UTF-8.
- Используйте UTF-8 в качестве выходной кодировки (не забудьте отправить подходящие
Content-type
заголовки).
- Установите соединение с базой данных для использования UTF-8 (
SET NAMES UTF8
в MySQL).
- Сконфигурируйте все остальное, чтобы оно было UTF-8, если это вообще возможно.
- Для всего, что вы не можете контролировать (например, сторонние веб-сервисы), убедитесь, что вы знаете кодировку, и конвертируйте в UTF-8 как можно раньше, и возвращайтесь к другой кодировке как можно позже.
Почему UTF-8? Поскольку он может представлять все символы Unicode и, таким образом, заменяет все существующие 7-разрядные и 8-разрядные кодировки, а также потому, что он двоично совместим с ASCII, то есть каждая допустимая строка ASCII также является допустимой строкой UTF-8 (но не vv .).
В вашем примере, что происходит, это.
Сначала вы сохраняете свой исходный файл; ваш текстовый редактор, вероятно, настроен на использование UTF-8, поэтому ваш строковый литерал заканчивается в кодировке UTF-8 на диске. PHP читает этот файл, интерпретируя строку как последовательность байтов; $original
теперь содержит строку из 7 символов в кодировке UTF-8, которая представляет собой последовательность байтов (хотя она содержит более 7 байтов, поскольку каждый символ представлен двумя или более байтами). Если вы затем позвоните echo $original
, закодированная строка будет отправлена клиенту как есть; если вы сказали клиенту ожидать UTF-8, все в порядке, но если нет, PHP не сможет определить разницу, и вы получите мусор в браузере. В качестве эксперимента попробуйте это:
$original = "शक्नोम्यत्तुम्";
echo strlen($original);
strlen
не зависит от кодировки и предполагает 8-битное кодирование с фиксированной шириной, то есть один байт на символ, поэтому он будет считать байты, а не символы.