Лучшие практики PHP utf-8 и риски для распределенных веб-приложений

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

Я хочу добавить полную поддержку utf-8 в разработанное мной приложение DaDaBIK; приложение можно использовать с разными СУБД (такими как MySQL, PostgreSQL, SQLite). Кодировка, используемая в базах данных, может быть ЛЮБОЙ. Я не могу установить или принять кодировку.

Мой подход будет заключаться в преобразовании с использованием функций iconv всего, что я читаю из БД в utf-8, а затем конвертации обратно в исходную кодировку, когда мне нужно записать в БД. Это позволило бы мне предположить, что я работаю с utf-8.

Проблема, как вы, вероятно, знаете, заключается в том, что PHP изначально не поддерживает utf-8, и даже если предположить, что используется mbstring, существуют (согласно http://www.phpwact.org/php/i18n/utf-8) несколько функций PHP, которые могут создавать проблемы с utf-8 и НЕ имеют соответствие mbstring, например расширение PREG, strcspn, trim, ucfirst, ucwords....

Поскольку я использую некоторые внешние библиотеки, такие как adodb и htmLawed, я не могу контролировать весь исходный код... в этих библиотеках есть несколько случаев использования этих функций... у вас есть какой-нибудь совет? И, прежде всего, как очень популярные приложения, такие как wordpress и т. д., справляются с этой (ИМХО большой) проблемой? Я сомневаюсь, что у них нет никакой «обрезки» в коде… они просто берут на себя риск (например, повреждение данных) или есть что-то, чего я не вижу?

Большое спасибо.


person Eugenio    schedule 05.09.2012    source источник
comment
PHP изначально не поддерживает utf-8?   -  person Passerby    schedule 05.09.2012
comment
Хорошо, некоторые строковые функции PHP изначально не поддерживают UTF-8. Я думал, что было довольно ясно, что я имел в виду, учитывая контекст.   -  person Eugenio    schedule 05.09.2012


Ответы (1)


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

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

Единственная реальная проблема — это функции, которые работают со смещением, например substr. Функции по умолчанию работают со смещением в байтах, в то время как на самом деле вам нужно более интеллектуальное смещение символов, которое не обязательно соответствует байтам. Для этих функций обычно существует эквивалент mb_.

preg_ прекрасно поддерживает UTF-8, используя модификатор /u.

Если у вас есть библиотека, которая использует, например, substr в потенциальной многобайтовой строке, используйте другую библиотеку, потому что это плохая библиотека.

Дополнительные сведения см. в разделе Что необходимо знать каждому программисту о кодировках и наборах символов для работы с текстом. подробное обсуждение и демистификация PHP и наборов символов.

Далее не важно какие строки закодированы как в БД. Вы можете установить кодировку соединения для базы данных, которая заставит ее конвертировать все для вас и всегда будет возвращать вам данные в желаемой клиентской кодировке. Нет необходимости превращать все в иконку в PHP.

person deceze♦    schedule 05.09.2012
comment
Время дать вам BUMMER! Я НЕ задавал этот вопрос. Я был просто прохожим, который пришел посмотреть, на кого здесь можно положиться с таким гребаным терпением ;) - person Karma; 05.09.2012
comment
ОЙ! Извините за это. Вы двое похожи. X-D - person deceze♦; 05.09.2012
comment
А вот теперь я запутался, так как в комментариях к вопросу есть еще один Прохожий... О_о;;? - person deceze♦; 05.09.2012
comment
Я только что проверил ваш блог через ваш профиль. Потрясающие вещи. Написать книгу. -___- - person Karma; 05.09.2012
comment
Да, я буду, пока это Amazon :) - person Karma; 05.09.2012
comment
Хе-хе. Посмотрим, может быть, когда-нибудь... :) - person deceze♦; 05.09.2012
comment
Есть много основ, которые мы, разработчики, упустили! Вы указали их все (по крайней мере, все, что я мог придумать), я добавил ваш блог в закладки! - person Karma; 05.09.2012
comment
Конечно, я имел в виду строковые функции; Я думал, что это понятно :) substr: его даже не было в списке, который я упомянул, есть эквивалент mbstring, так что, конечно, проблем нет. Обрезка: если во 2-м параметре стоит многобайтный char, то есть риск, это довольно очевидно. PREG: страница, которую я упомянул, довольно хорошо объясняет риски, если вы считаете, что это объяснение имеет некоторые недостатки, вы должны предложить контраргументы. И есть риски также с strcspn,ucfirst,ucwords. Наконец, вы уверены, что ваше последнее предложение верно для всех популярных СУБД? Признаюсь, я не уверен, я буду исследовать это. - person Eugenio; 05.09.2012
comment
@ Eugenio Я не могу воспринимать эту страницу слишком серьезно. Пример: htmlentities, Риск: высокий, [...] Слух — хотя эта функция (утверждает) имеет поддержку UTF-8, сообщения об ошибках утверждают, что она не работает, по крайней мере, до PHP 5. Использование ее в строке UTF-8 с неправильной кодировкой, скорее всего, приведет к повреждению / нежелательному выводу. Так что же это? ВЫСОКИЙ РИСК? Слух? Глючили в старых версиях? Только при неправильном использовании? Ну конечно, это моя точка зрения, при неправильном использовании почти все опасно. Также нет конкретных тестовых примеров для любого из утверждений на этой странице. Принимайте все это с недоверием. - person deceze♦; 05.09.2012
comment
@Eugenio Кроме того, некоторые вещи кажутся совершенно неправильными или устаревшими. Согласно этой странице, preg_match('/\w+/u', '漢字!!') не должно работать. Однако это так: codepad.viper-7.com/GKIpxG - person deceze♦; 05.09.2012
comment
@deceze Я действительно думаю, что эта страница очень хорошо сделана, поэтому она по-прежнему является одним из самых популярных источников, когда речь идет о многобайтности и PHP. Опять же, для функций PCRE и других, о которых я упоминал, объяснение имеет смысл, поэтому вы не можете просто сказать, что это неверно, не предложив встречных аргументов :) - person Eugenio; 05.09.2012
comment
@Eugenio Пожалуйста, расскажите поподробнее. Каков риск? В отношении PCRE есть три момента: 1) модификатор /i, который говорит Если не используется модификатор /u... как его единственный риск, который, опять же, сводится к правильному его использованию. . 2) Сам модификатор /u, который указывает только настоящую непроблему как проблему. 3) Классы \w и \b, которые я продемонстрировал как некорректную проблему. - person deceze♦; 05.09.2012
comment
@Eugenio Также обратите внимание, что эта страница существенно не обновлялась с 2006 года! Если и были какие-то ошибки, то, скорее всего, с тех пор все они были исправлены. Для большинства других функций, которые они перечисляют, в значительной степени сводится к пониманию того, что это делает, и правильному использованию, что я и говорю. - person deceze♦; 05.09.2012
comment
Итак... strcspn является безопасной функцией UTF8? Могу ли я использовать его в контексте UTF8? - person Peter Krauss; 12.10.2014
comment
@PeterKrauss Я считаю, что так и должно быть, нет ничего, что по своей сути требовало бы, чтобы эта функция понимала кодировки. Однако имейте в виду, что возвращаемое значение будет считаться байтами, а не символами. - person deceze♦; 13.10.2014