Jakie czynniki powodują, że PHP jest niekompatybilny z Unicode?

Jestem w stanie używać znaków UTF-8 w moich skryptach.

W rzeczywistości możliwe jest aby nazwy zmiennych i funkcji zawierały znaki Unicode .

Istnieje również rozszerzenie mb_string, które zajmuje się ciągami wielobajtowymi, jednak w niezliczonych artykułach PHP jest krytykowane za brak obsługi Unicode.

Nie rozumiem, dlaczego PHP mówi, że nie obsługuje Unicode?

 38
Author: Leigh, 2009-02-21

7 answers

Kiedy PHP zostało uruchomione kilka lat temu, UTF-8 nie był tak naprawdę obsługiwany. Mówimy o czasach, kiedy nie-Unicode OS jak Windows 98 / Me był nadal aktualny i kiedy inne duże języki, takie jak Delphi były również nie-Unicode. Nie wszystkie języki zostały zaprojektowane z myślą o Unicode od pierwszego dnia, a całkowita zmiana języka na Unicode bez łamania wielu rzeczy jest trudna. Delphi stało się kompatybilne z Unicode rok lub dwa temu, na przykład, podczas gdy inne języki, takie jak Java lub C# były zaprojektowany w Unicode od 1 dnia.

Więc kiedy PHP rosło i stało się PHP 3, PHP 4, a teraz PHP 5, po prostu nikt nie zdecydował się dodać Unicode. Dlaczego? Prawdopodobnie, aby zachować zgodność z istniejącymi skryptami lub ponieważ utf8_de / encode i mb_string już istniały i działają. Nie wiem na pewno, ale mocno wierzę, że ma to coś wspólnego ze wzrostem organicznym. Funkcje nie istnieją po prostu domyślnie, muszą być napisane przez kogoś, a to po prostu nie stało się jeszcze dla PHP.

Edit: Ok, Źle przeczytałem pytanie. Pytanie brzmi: w jaki sposób łańcuchy są przechowywane wewnętrznie? Jeśli wpiszę "Währung "lub " Écriture", które kodowanie jest używane do tworzenia używanych bajtów? W przypadku PHP jest to ASCII ze stroną kodową. Oznacza to, że jeśli zakoduję ciąg za pomocą ISO-8859 - 15, a Ty dekodujesz go za pomocą jakiejś chińskiej strony kodowej, otrzymasz dziwne wyniki. Alternatywa jest w językach takich jak C# lub Java, gdzie wszystko jest przechowywane jako Unicode, co oznacza: nie ma już strony kodowej i teoretycznie nie można spierdol. Polecam artykuł Joela o Unicode i zestawach znaków, ale zasadniczo sprowadza się to do: jak łańcuchy są przechowywane wewnętrznie, a odpowiedź w PHP brzmi "Nie w Unicode", co oznacza, że musisz być bardzo ostrożny i wyraźny podczas przetwarzania łańcuchów, aby upewnić się, że zawsze utrzymujesz łańcuch w odpowiednim kodowaniu podczas wprowadzania, przechowywania (bazy danych) i wyjścia, co jest bardzo błędne.

 39
Author: Michael Stum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-11 12:49:14

Uważam, że jest to w dużej mierze trudność kulturowa, a nie techniczna.

Jeśli chodzi o problemy techniczne- - - i nie całkiem trywialne jest implementowanie unicode w ekosystemie zbudowanym na założeniach, że "jeden znak równa się jeden bajt" - - - programiści mogli skopiować wiele wysiłków Javy lub Pythona (ten ostatni z przyzwoitą i w dużej mierze działającą zgodnością z unicode od około 2001 roku), ale nigdy tego nie zrobili.

Kiedy czytam wątek dyskusyjny dołączony do oficjalna, aktualna dokumentacja dla funkcji utf8_encode() php, mam zawroty głowy.

Firstoff, funkcja ta jest wywoływana utf8_encode(); jednak dokumentacja stwierdza, że oczekiwany ciąg znaków powinien znajdować się w ISO-8859-1 (a.K.a. latin-1). to sooo php, to sooo 80s.

Większość komentatorów zdaje się postrzegać unicode jako ciężar. istnieje wiele propozycji jak konwertować ciągi 'o nieznanej zawartości', jak radzić sobie z 'strunami' z kodowaniem mieszanym ' (wtf?), lub zajmowanie się Punkty kodowe, które normalnie powodują złamanie, ponieważ przekraczają limit czterech bajtów na punkt kodowy tej funkcji.

Dyskusja koncentruje się wokół poprawek, aby pozbyć się zawijasów lub uniknąć problematycznych części zachowania tej funkcji. i to, jak dla mnie, jest sooo php: każdy robi tylko poprawki, kilka rzeczy są zaimplementowane w zasadniczo poprawny sposób. jeśli uważasz, że to oszczerstwo po mojej stronie, oto kilka ciekawostek:

Chociaż wydaje się to łamać Niemiecki Umlaute [äöü] jeśli dokument jest już UTF-8.

(brak zrozumienia, że utf-8 nie jest zaprojektowany do działania, gdy jest stosowany dwa razy)

Spójrz na funkcję iconv (), która oferuje sposób na konwersję z 8859 i 1252 do UTF8

[6]} (dobry punkt: zaniedbanie wcześniejszych artów ze strony programistów php; zamiast tego błędna implementacja własna)

Użycie preg_match do wykrycia, czy potrzebny jest utf8_encode [...] z wyłączeniem surogatów [...] wyłączając overlongs

(sugerując, aby po cichu usunąć wszystkie problematyczne treści z ciągów, pozostawiając tylko te rzeczy, które nie pękają utf8_encode(); może to spowodować, że teksty będą nieczytelne (lub znikną całkowicie), ale koniec z komunikatami o błędach)

Aby zakodować ciąg znaków tylko wtedy, gdy nie jest jeszcze UTF-8 [...] mb_detect_encoding($s, "UTF-8")

(Jak zauważył inny komentator , to się nie uda:

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

Więc tutaj patrzymy na jeden błąd zastępowany przez inny. happy polowanie. ponadto, wydaje się, że proponują tutaj rozwiązanie problemu za pomocą heurystycznych (powolnych, niepewnych) środków, które mogłyby i powinny być rozwiązane za pomocą mechanicznych (szybkich, pewnych) środków)

Utf8_ [kodowanie|dekodowanie] faktycznie przetłumaczy również windows - 1252 znaki, a nie tylko z / do ISO-8859-1, Jak mówi dokumentacja

(nigdy nie można polegać na oficjalnej dokumentacji php, aby była jasna lub wyczerpująca - - - zawsze musisz przeczytać lata doświadczeń użytkowników, które nikt nigdy nie pożyje się do docs)

Pracowałem nad funkcją is_utf8 i chciałem ją tutaj opublikować, oprócz innych wziąłem również pod uwagę błąd 5000 char

(poprawka problemu, który w dużej mierze istnieje tylko dlatego, że unicode nie jest poprawnie zaimplementowany. dowiadujemy się również, że nie tylko funkcja utf8_encode() da więcej niż 4 bajty na punkt kodowy, ale również ulegnie awarii, jeśli wynik (lub wyjście?) tekst przekracza limit 5000 znaków)

I może tak dalej i dalej. już masz pomysł: sądząc po tym wątku, społeczność php po prostu nie brzmi tak, jakby była gotowa pojąć, o co chodzi w kodowaniu i zestawach znaków, czego potrzeba, aby zbudować infrastrukturę dźwiękową w ogóle lub, w szczególności, aby zaimplementować unicode w odpowiedni sposób. zamiast tego używają swoich rusztowań, kartonów, gwoździ i młotów i budują ten wielki Gmach zwany php, rzucając taśmą klejącą na każdy problem nie da się tego cofnąć innym gwoździem. oczywiście ten budynek będzie cierpiał z powodu każdego wiatru, który wieje, jak na przykład sporadyczny legalny, ale nieoczekiwany charakter.

Widząc ten konkretny wątek aktywny przez osiem lat, nie wzbudza pewności, że sytuacja będzie lepsza za osiem lat.

 33
Author: flow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 06:11:23

Koncepcja "znaku wielobajtowego" jest sednem problemu.

  1. ujawnia szczegóły implementacji: powinieneś być w stanie pracować z abstrakcją znaku, nie wiedząc, w jaki sposób implementatorzy wybierają reprezentowanie danych - może w zależności od platformy pasuje im do reprezentowania wszystkiego jako UTF16 lub UTF32, w którym to przypadku wszystko jest wielobajtowe, a nie, że użytkownicy abstrakcji znaków powinni dbać.
  2. to kludge: na szczycie nieaktualnego nawyk myślenia tam, gdzie wszyscy "naprawdę wiemy", że ciągi znaków są sekwencjami bajtów, musimy teraz wiedzieć, że czasami bajty zlewają się ze sobą w rzeczy znane jako znaki Unicode i mają specjalne przypadki w całym miejscu, aby sobie z tym poradzić.
  3. To jak mysz próbująca zjeść słonia. Poprzez kadrowanie Unicode jako rozszerzenia ASCII (mamy normalne ciągi znaków i mamy mb_strings), to dostaje rzeczy źle wokół, i zostaje zawieszony na jakie specjalne przypadki są wymagane, aby radzić sobie ze znakami z zabawnymi zawijasami, które potrzebują więcej niż jednego bajtu. Jeśli traktujesz Unicode jako abstrakcyjną przestrzeń dla dowolnego znaku, ASCII jest w tym uwzględniane bez potrzeby traktowania go jako specjalnego przypadku.
 11
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-26 18:12:26

Mówisz to sam: aby poprawnie radzić sobie z ciągami zawierającymi wielobajtowe znaki, musisz użyć rozszerzenia. Zapomnij gdziekolwiek używać funkcji rozszerzenia zamiast tych bardziej znanych "normalnych", a Twoje dane zostaną zniszczone. To samo dzieje się w przypadku korzystania z biblioteki innej firmy, która nie została zaktualizowana w celu korzystania z funkcji rozszerzenia wszędzie.

Ponadto wiele niezwykle popularnych kodowań jest nadal jawnie Nie wspieranych przez PHP, prawdopodobnie dlatego, że jest to niemożliwe, aby to zrobić i pozostać zgodnym w dół.

 5
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-21 00:22:18

Wiele popularnych rozszerzeń nie obsługuje unicode lub (co gorsza) musisz wiedzieć, że ciąg znaków zawiera sekwencje unicode / utf-8, Jak na przykład XMLReader. I może to zrobić sporą różnicę w wywołaniu funkcji glob () PHP przez FindFirstFileA lub FindFirstFileW na win32.
Innym (znacznie mniejszym, ale zaskakująco często będącym źródłem irytacji) problemem są BOM, których PHP nie rozpoznaje.

 3
Author: VolkerK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-21 00:25:55

Wiele funkcji łańcuchowych jest tylko cienkimi opakowaniami wokół odpowiedników biblioteki C, które również traktują wszystko jako sekwencję bajtów. Innym powodem jest to, że PHP niesie ze sobą wiele niepotrzebnego bagażu wstecznej kompatybilności, a tym samym utknie z błędnymi decyzjami projektowymi z 3 i 4.

Może z przestrzeniami nazw 5.3 będą w końcu mieli sposób na stopniowe wycofywanie starych funkcji.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-21 00:28:51

Co oznacza "wsparcie" to "natywne wsparcie". Spójrz na to , aby uzyskać szczegółowe informacje.

 2
Author: muratgu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-21 00:06:29