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.