Многострочные строковые функции PHP

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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

Например:

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

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

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

Ответ 4

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

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

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

Ответ 5

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

http://sourceforge.net/projects/phputf8

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