Статьи

Кодировки и ввод символов

Когда-нибудь запускали свой PHP-сайт, управляемый базой данных, через валидатор HTML и встречали сообщение об ошибке, подобное этому?

Строка 9, столбец 3: не символ SGML № 145

Хуже того, вы когда-нибудь запускали свой сайт XHTML через валидатор XHTML как XHTML и сталкивались с таким сообщением об ошибке, как это?

Извините, я не могу проверить этот документ, потому что в строке 9 он содержал один или несколько байтов, которые я не могу интерпретировать как utf-8

Если это так, то у вас есть блюз кодировки символов.

Текстовые форматы используют кодировки символов для сопоставления символов с их двоичным представлением. При использовании только символов в диапазоне ASCII (американский английский) кодирование символов, похоже, «просто работает». Вы можете даже не знать о кодировке символов, которую вы используете. Это связано с тем, что символы ASCII представлены одинаково во всех популярных кодировках символов, используемых в Интернете, поэтому, если вам никогда не нужен чужой символ, вы никогда не столкнетесь с проблемой. Однако, как только вы отклонитесь от этого общего знаменателя символов ASCII и начнете использовать символы из иностранных языков, их представление в двоичной форме может зависеть от используемой кодировки символов, и если вы запутаете кодировку, вы можете получить недопустимые символы.

Проблема в том, что если вы пишете свое PHP-приложение, используя, скажем, кодировку символов ISO-8859-1, которая является наиболее распространенной в HTML, вы не можете полагаться на то, что все входные данные PHP действительны в этой кодировке символов. Браузеры обычно игнорируют или не знают о кодировке символов, которую хочет ваше приложение. ISO-8859-1 содержит зарезервированные значения, которые не должны использоваться, однако, если вы копируете документ Word в веб-форму и отправляете его, скопированный текст может содержать символы кодовой страницы Windows 1252 (Windows-1252), которые недействительны в ISO-8859-1.

Если эти символы затем отображаются в CMS, полученные страницы не будут проверены. Или, если вы используете XHTML в качестве XML, страница не будет отображаться вообще!

К сожалению, PHP не имеет возможности преобразовывать кодировки символов или проверять строку, чтобы убедиться, что она допустима в конкретной кодировке символов. То есть, если вы не включите расширение mbstring (по умолчанию отключено). Расширение mbstring поддерживает огромное количество кодировок символов, распространенных и необычных. Он может преобразовывать строку из одной кодировки символов в другую, выполнять множество функций над строками, которые в противном случае могли бы не учитывать кодировку символов (например, изменять регистр букв), и даже может анализировать ввод данных из форм для вас.

Если вы не можете установить расширение mbstring, вам может понадобиться быстрое исправление. Если вы используете кодировку ISO-8859-1 в своей CMS, вы можете использовать следующее регулярное выражение для удаления любых символов, которые недопустимы в этой кодировке:


// strip out characters that aren't valid in ISO-8859-1
$string = preg_replace('/[^x09x0Ax0Dx20-x7FxC0-xFF]/', '', $string);

Лучшим решением для этого было бы использовать внутреннюю кодировку символов, которая может представлять любой символ в любой другой кодировке. Кодировка символов Unicode способна на это, и UTF-8 — кодировка символов Unicode, которая представляет символы ASCII как отдельные байты, а другие символы — как несколько байтов, является хорошим выбором. К сожалению, без mbstring или сторонней библиотеки использование UTF-8 для внутреннего использования нецелесообразно. Трудно отсеять символы, которые являются недопустимыми в UTF-8, или преобразовать из других форматов в UTF-8 (функция utf8_encode не может обнаружить или отфильтровать недопустимые символы — она ​​просто предполагает, что ввод действителен ISO-8859-1).

Комментарии в функции utf8_encode демонстрируют проблемы, возникающие у людей с кодировкой символов в их коде.