PHP многобайтовые строковые функции

Сегодня я столкнулся с проблемой с функцией PHP strpos() потому что он возвращал FALSE, даже если правильный результат был, очевидно, 0. Это было потому, что один параметр был закодирован в UTF-8, а другой (источник - это параметр HTTP GET), очевидно, нет.

Теперь я заметил, что с помощью mb_strpos Функция решила мою проблему.

Мой вопрос сейчас: разумно ли использовать многобайтовые строковые функции PHP в целом, чтобы избежать этих проблем в будущем? Должен ли я избежать традиционного strpos, strlen, eregи т.д. и т.п. функционирует вообще?

Обратите внимание: я не хочу устанавливать mbstring.func_overload глобальный в php.ini, потому что это приводит к другим проблемам при использовании библиотеки PEAR. Я использую PHP4.

5 ответов

Решение

Это зависит от используемой вами кодировки символов. В однобайтовых кодировках символов или UTF-8 (где один байт внутри символа никогда не может быть ошибочно принят за другой символ), тогда пока строка, в которой вы ищете, и строка, которую вы используете для поиска, находятся в одном и том же кодирование, то вы можете продолжать использовать обычные функции поиска строки.

Если вы используете многобайтовую кодировку, отличную от UTF-8, которая не препятствует тому, чтобы отдельные байты в символе появлялись как другие символы, то всегда невозможно выполнить поиск строки, используя обычные функции поиска строки. Вы можете найти ложные срабатывания. Это связано с тем, что сравнение строк в PHP в таких функциях, как strpos, выполняется по байтам, и, за исключением UTF-8, специально разработанного для предотвращения этой проблемы, многобайтовые кодировки страдают от проблемы, которая возникает из любого последующего байта символа более одного байта может соответствовать части другого символа.

Если искомая строка и искомая строка имеют разные кодировки символов, то преобразование всегда будет необходимо. В противном случае вы обнаружите, что для любой строки, которая будет представлена ​​по-другому в другой кодировке, она всегда будет возвращать false. Вы должны сделать такое преобразование при вводе: определитесь с кодировкой символов, которую будет использовать ваше приложение, и будьте последовательны в приложении. Каждый раз, когда вы получаете ввод в другой кодировке, конвертируйте по пути.

Были некоторые проблемы с функциями mb_ * в версиях PHP до 5.2. Так что, если ваш код работает на нескольких платформах с разными версиями PHP, может произойти странное поведение. Кроме того, функция mb_ strpos довольно медленная, она должна пропускать количество символов, указанное параметром смещения, чтобы получить реальную позицию байта, используемую внутри. В циклах в зависимости от функциональности strpos / mb_strpos это может стать основным узким местом.

Если вы используете одну и ту же кодировку везде, это, как правило, не проблема. Я использую UTF-8 для всех своих страниц и никогда не сталкивался с этой проблемой. В конце концов, все сводится к указанию одинаковой кодировки для страниц и базы данных.

Например:

header('Content-type: text/html;charset=utf-8');
mysql_query('SET NAMES utf8');

В большинстве случаев это означает, что все источники данных для приложения будут доставлять данные в одной и той же кодировке, и, таким образом, вы избежите подобных проблем.

Все это будет намного лучше с появлением PHP 6, кстати, так как он будет включать полную поддержку Unicode.

Вам не обязательно использовать mb_strpos, но вам нужно убедиться, что все данные в вашем приложении одинаковы: либо mb_string, либо простая строка в одной конкретной кодировке. (Обычно UTF-8.)

Если вы убедитесь, что ваши страницы соответствуют UTF-8, а отправленные вами формы интерпретируются как UTF-8, а ваша база данных хранит UTF-8, вы, как правило, будете в порядке. Операции с индексированными строками (в частности, усечения) могут нарушать последовательность UTF-8, что раздражает, но, как правило, не губительно. Если вам нужен такой уровень поддержки, mb_strings - это ваш единственный вариант (но, конечно, вы должны убедиться, что все части вашего приложения, а также библиотеки и версия PHP справятся с ними должным образом).

Разработка сайтов, которые правильно обрабатывают Unicode в PHP, сейчас не слишком увлекательна: ее поддержка Unicode очень плохая по сравнению с такими языками, как Python и.NET. Есть надежда, что PHP6 улучшит ситуацию.

Я бы порекомендовал использовать следующую библиотеку PHP UTF-8:

http://sourceforge.net/projects/phputf8

Связывание его с вашим приложением ослабляет требования вашего приложения, не требуя расширения mbstring, но вы все равно получаете строковые функции UTF-8.

Другие вопросы по тегам