Какие факторы делают PHP Unicode-несовместимым? - PullRequest
42 голосов
/ 21 февраля 2009

Я могу использовать символы UTF-8 в своих скриптах.

На самом деле может иметь имена переменных, а функции содержат символы Unicode .

Существует также расширение mb_string , которое работает с многобайтовыми строками, однако в бесчисленных статьях PHP подвергается критике за отсутствие поддержки Unicode.

Я не понимаю; почему PHP не поддерживает Unicode?

Ответы [ 7 ]

44 голосов
/ 21 февраля 2009

Когда PHP был запущен несколько лет назад, UTF-8 действительно не поддерживался. Мы говорим о времени, когда не-Unicode ОС, такая как Windows 98 / Me, была все еще актуальна, и когда другие крупные языки, такие как Delphi, также не были Unicode. Не все языки были разработаны с учетом Unicode с первого дня, и полностью изменить свой язык на Unicode, не ломая много вещей, сложно. Например, Delphi стал Unicode-совместимым только год или два назад, в то время как другие языки, такие как Java или C #, были разработаны в Unicode с первого дня.

Итак, когда PHP вырос и стал PHP 3, PHP 4, а теперь и PHP 5, просто никто не решил добавить Unicode. Зачем? Предположительно для обеспечения совместимости с существующими сценариями или потому что utf8_de / encode и mb_string уже существуют и работают. Я не знаю наверняка, но я твердо верю, что это как-то связано с органическим ростом. Функции не просто существуют по умолчанию, они должны быть кем-то написаны, а для PHP этого просто не произошло.

Редактировать: Хорошо, я неправильно прочитал вопрос. Вопрос: как строки хранятся внутри? Если я введу «Währung» или «Écriture», то какая кодировка используется для создания используемых байтов? В случае PHP это ASCII с кодовой страницей. Это означает: если я закодирую строку, используя ISO-8859-15, и вы расшифруете ее с использованием некоторой китайской кодовой страницы, вы получите странные результаты. Альтернатива в таких языках, как C # или Java, где все хранится как Unicode, что означает: кодовой страницы больше нет, и теоретически вы не можете испортить. Я рекомендую статью Джоэла о Юникоде и наборах символов, но по сути это сводится к следующему: как строки хранятся внутри, а ответ с PHP - «Не в Юникоде», что означает, что вы должны быть очень осторожны и явное при обработке строк, чтобы всегда сохранять строку в правильной кодировке во время ввода, хранения (базы данных) и вывода, что очень подвержено ошибкам.

36 голосов
/ 30 апреля 2011

Я считаю, что это во многом культурная, а не техническая проблема.

что касается технических проблем --- и не совсем просто реализовать юникод в экосистеме, основанной на предположении, что «один символ равен одному байту» - разработчики могли бы скопировать большую часть усилий Java или Python (последний с достойной и в значительной степени работающей совместимостью с юникодом примерно с 2001 года), но они так и не сделали.

когда я читаю ветку обсуждения, прилагаемую к официальной, текущей документации по utf8_encode() функции php , я чувствую головокружение.

во-первых, эта функция называется utf8_encode(); однако, в документации говорится, что ожидаемая строка должна быть в ISO-8859-1 (a.k.a. latin-1). это ооочень php, это ооочень 80-х годов.

большинство комментаторов, похоже, воспринимают юникод как бремя. Есть много предложений о том, как преобразовать строки «неизвестного содержимого», как обращаться с s «строками со смешанным кодированием» (wtf?) или работать с кодовыми точками, которые обычно вызывают сбой, потому что они выходят за рамки четырехбайтной функции. предел кодовой точки.

обсуждение сосредоточено вокруг исправлений, чтобы избавиться от закорючек или избежать проблемных частей поведения этой функции. и это, для меня, sooo php: все просто делают исправления, мало что реализовано в корне правильно. если вы считаете, что это клевета на мою сторону, вот некоторые лакомые кусочки:

Хотя это, кажется, нарушает немецкий Umlaute [äöü], если документ уже UTF-8.

(непонимание того, что utf-8 не предназначен для работы при двойном применении)

Посмотрите на функцию iconv (), которая предлагает способ конвертации из 8859 и страшных 1252 в UTF8

(хороший момент: пренебрежение предшествующим уровнем техники со стороны разработчиков php; вместо этого глючит собственная реализация)

использование preg_match для определения необходимости использования utf8_encode [...], исключая суррогаты [...], исключая переопределения

(предлагает молча стереть весь проблемный контент из строк, оставляя только те вещи, которые не ломаются utf8_encode(); это может сделать текст нечитаемым (или вообще исчезнуть), но, эй, больше сообщений об ошибках)

для кодирования строки, только если это еще не UTF-8 [...] mb_detect_encoding($s, "UTF-8")

(как указано другим комментатором , это не сработает:

$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false

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

utf8_ [кодировать | декодировать] фактически будет также переводить символы windows-1252, а не только из / в ISO-8859-1, как сказано в документации

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

Я работал над функцией is_utf8 и хотел опубликовать ее здесь, в дополнение к другим, я также учел ошибку в 5000 символов

(исправление для проблемы, которая в основном существует только потому, что юникод не реализован должным образом. Мы также узнаем, что функция utf8_encode() не только откажется за пределы 4 байтов на кодовую точку, она также сломается, если полученная ?) текст превышает ограничение в 5000 символов)

Я мог бы продолжать и продолжать в том же духе. у вас уже есть идея: судя по этой теме, сообщество php просто не похоже, что они где-то готовы понять, что такое кодировки и наборы символов, что нужно для создания звуковой инфраструктуры в целом или, в частности, для реализовать Юникод надлежащим образом. вместо этого они используют свои строительные леса, картон, гвозди и молотки и продолжают строить это грандиозное здание, называемое php, бросая клейкую ленту на все проблемы, которые невозможно устранить другим гвоздем. Конечно, это здание будет страдать от каждого дующего ветра, такого как случайный юридический, но неожиданный характер.

наблюдение за тем, как эта конкретная нить активна в течение восьми лет, не вселяет уверенности, что через восемь лет ситуация будет лучше.

11 голосов
/ 26 февраля 2009

Концепция «многобайтового символа» лежит в основе проблемы.

  1. Утечка деталей реализации: у вас должна быть возможность работать с абстракцией символа, не зная, как разработчики выбирают представление данных - возможно, в зависимости от платформы, для которой они подходят, чтобы представлять все как UTF16 или UTF32, в которых В случае, если все является многобайтовым, не то, чтобы пользователи абстракции символа должны были заботиться.
  2. Это клочок: поверх устаревшей привычки мысли, когда все мы «действительно знаем», что строки - это последовательности байтов, теперь мы должны знать, что иногда байты объединяются в вещи, известные как символы Юникода, и есть специальные случаи повсюду, чтобы иметь дело с этим.
  3. Это как мышь, пытающаяся съесть слона. Обрамляя Unicode как расширение ASCII (у нас есть нормальные строки и у нас есть mb_strings), он неправильно понимает ситуацию и зацикливается на том, какие особые случаи требуются для работы с персонажами со смешными загадками, которым требуется более одного байта. Если вы рассматриваете Юникод как предоставление абстрактного пространства для любого нужного вам символа, ASCII учитывает это без необходимости рассматривать его как особый случай.
5 голосов
/ 21 февраля 2009

Вы говорите сами: чтобы правильно обрабатывать строки, содержащие многобайтовые символы, вам нужно использовать расширение. Забудьте где-нибудь использовать функции расширения вместо более привычных «обычных», и ваши данные изуродованы. То же самое происходит, если вы используете стороннюю библиотеку, которая не была обновлена, чтобы везде использовать функцию расширения.

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

3 голосов
/ 21 февраля 2009

Многие строковые функции являются просто тонкими обертками вокруг эквивалентов библиотеки C, которые также обрабатывают все как последовательность байтов. Другая причина в том, что PHP несет в себе много ненужного багажа с обратной совместимостью и, следовательно, застревает в плохих дизайнерских решениях 3 и 4.

Возможно, с помощью пространств имен 5.3 у них наконец-то появится способ поэтапного отказа от старых функций.

3 голосов
/ 21 февраля 2009

Многие из распространенных расширений не поддерживают Unicode, или (что еще хуже) вам «нужно знать», что строка содержит последовательности Unicode / UTF-8, как, например, XMLReader. И это может сильно изменить ситуацию, когда глобальные вызовы PHP () вызывают FindFirstFileA или FindFirstFileW на win32.
Другая (гораздо меньшая, но на удивление часто вызывающая раздражение) проблема - это спецификации, которые PHP не распознает.

2 голосов
/ 21 февраля 2009

Под «поддержкой» подразумевается «собственная поддержка». Посмотрите на это , чтобы получить подробную информацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...