Łańcuch PHP jest tylko sekwencją bajtów, bez żadnego kodowania. Wartości łańcuchowe mogą pochodzić z różnych źródeł: klienta (przez HTTP), bazy danych, pliku lub literałów łańcuchowych w kodzie źródłowym. PHP czyta je wszystkie jako sekwencje bajtów i nigdy nie wyodrębnia żadnych informacji o kodowaniu.
Tak długo, jak wszystkie źródła danych i miejsca docelowe używają tego samego kodowania, najgorsze, co może się zdarzyć, to nieprawidłowe pozycje pozycji (jeśli używasz kodowania wielobajtowego), ponieważ PHP będzie liczyć bajty, a nie znaki.
Ale jeśli kodowania się nie zgadzają (np. Piszesz literał łańcuchowy w pliku źródłowym przechowywanym jako UTF-8, a następnie wysyłasz go do bazy danych, która oczekuje Latin-1), PHP nie wykona dla ciebie żadnej konwersji: wykona szczęśliwie skopiuj bajty na raw.
Najlepszym rozwiązaniem jest:
- Ustaw wewnętrzne kodowanie PHP na UTF-8.
- Zapisz wszystkie pliki źródłowe jako UTF-8.
- Użyj UTF-8 jako kodowania wyjściowego (nie zapomnij wysłać odpowiednich
Content-type
nagłówków).
- Ustaw połączenie z bazą danych, aby używało UTF-8 (
SET NAMES UTF8
w MySQL).
- Skonfiguruj wszystko inne, aby było UTF-8, jeśli to w ogóle możliwe.
- W przypadku czegokolwiek, czego nie możesz kontrolować (np. Usług internetowych stron trzecich), upewnij się, że znasz kodowanie, i przekonwertuj na UTF-8 tak wcześnie, jak to możliwe, a następnie wróć do innego kodowania tak późno, jak to możliwe.
Dlaczego UTF-8? Ponieważ może reprezentować wszystkie znaki Unicode, a tym samym zastępuje wszystkie istniejące kodowania 7-bitowe i 8-bitowe oraz ponieważ jest binarnie zgodny z ASCII, to znaczy, każdy prawidłowy ciąg ASCII jest również prawidłowym ciągiem UTF-8 (ale nie vv .).
W twoim przykładzie tak się dzieje.
Najpierw zapisz plik źródłowy; Twój edytor tekstowy jest prawdopodobnie skonfigurowany do używania UTF-8, więc literał łańcuchowy kończy się kodowaniem UTF-8 na dysku. PHP czyta ten plik, interpretując ciąg znaków jako ciąg bajtów; $original
teraz zawiera ciąg znaków zakodowany w UTF-8 składający się z 7 znaków, który jest tylko sekwencją bajtów (chociaż zawiera więcej niż 7 bajtów, ponieważ każdy znak jest reprezentowany przez dwa lub więcej bajtów). Jeśli następnie zadzwonisz echo $original
, zakodowany ciąg zostanie wysłany do klienta w niezmienionej postaci; jeśli powiedziałeś klientowi, aby spodziewał się UTF-8, wszystko jest w porządku, ale jeśli nie, PHP nie ma sposobu na odróżnienie, a skończysz na śmieciach w przeglądarce. W ramach eksperymentu spróbuj tego:
$original = "शक्नोम्यत्तुम्";
echo strlen($original);
strlen
jest agnostyczny dla kodowania i zakłada 8-bitowe kodowanie o stałej szerokości, to znaczy jeden bajt na znak, więc będzie liczyć bajty, a nie znaki.