PHP dahili olarak dizeleri nasıl temsil eder?


18

UTF8?
UTF16?

PHP'deki dizeler kullanılan kodlamayı da takip ediyor mu?

Örneğin bu senaryoya bakalım. Söyle koş:

$original = "शक्नोम्यत्तुम्";

Aslında ne olur?

Açıkçası bence $originalsadece 7 karakter olmayacak. Bu gliflerin her biri orada birkaç bayt ile temsil edilmelidir.

Sonra yaparım:

$converted = mb_convert_encoding ($original , "UTF-8");

Ne olacak $converted? Nasıl $convertedfarklı olacak $original?

Tam olarak aynı bayt dizisi olacak, $originalancak farklı bir kodlamaya sahip olacak mı?


1
Hangi PHP sürümü? PHP <6, yerel UTF-8'i işleyemez. Bu sorunu çözmeye yardımcı olan paketler ve yöntemler vardır. Utf-8 ve php ile Google eğlencesi. Ardından PHP yerine başka bir platforma geçin. :)
Andrew T Finnell

4
PHP <6? Bu şimdiye kadar yayınlanmış her PHP sürümünü içerir ...
tdammers

1
Ayrıca, PHP olabilir size ne yaptığınızı dışarı bakmak zorunda UTF-8 sap, sadece, özel bir veri türüne sahip değil.
tdammers

Yanıtlar:


22

Bir PHP dizesi sadece bir bayt dizisidir ve herhangi bir kodlaması etiketlenmemiştir. Dize değerleri çeşitli kaynaklardan gelebilir: istemci (HTTP üzerinden), veritabanı, dosya veya kaynak kodunuzdaki dize değişmezlerinden. PHP tüm bunları bayt dizileri olarak okur ve hiçbir zaman kodlama bilgisi çıkarmaz.

Tüm veri kaynaklarınız ve hedefleriniz aynı kodlamayı kullandığı sürece, olabilecek en kötü şey dize konumlarının yanlış olmasıdır (çok baytlı kodlamalar kullanıyorsanız), PHP karakterleri değil, baytları sayacaktır.

Ancak kodlamalar eşleşmezse (örneğin, UTF-8 olarak depolanan bir kaynak dosyaya bir dize hazır bilgisi yazıp Latin-1'i bekleyen bir veritabanına gönderirseniz), PHP sizin için herhangi bir dönüşüm gerçekleştirmez: baytları ham olarak mutlu bir şekilde kopyalayın.

En kolay çözüm şudur:

  • PHP'nin dahili kodlamasını UTF-8 olarak ayarlayın.
  • Tüm kaynak dosyalarınızı UTF-8 olarak kaydedin.
  • Çıktı kodlamanız olarak UTF-8 kullanın (uygun Content-typebaşlıkları göndermeyi unutmayın ).
  • Veritabanı bağlantısını UTF-8 kullanacak şekilde ayarlayın ( SET NAMES UTF8MySQL'de).
  • Mümkünse diğer her şeyi UTF-8 olacak şekilde yapılandırın.
  • Kontrol edemediğiniz herhangi bir şey için (örn. Üçüncü taraf web hizmetleri), kodlamayı bildiğinizden emin olun ve mümkün olduğunca erken UTF-8'e ve diğer kodlamaya geri dönün.

Neden UTF-8? Tüm Unicode karakterleri temsil edebildiğinden ve böylece mevcut tüm 7 bit ve 8 bit kodlamaların yerini aldığından ve ASCII ile ikili uyumlu olduğu için, yani her geçerli ASCII dizesi de geçerli bir UTF-8 dizesidir (ancak vv değil) .).

Örneğinizde, olan budur.

İlk olarak, kaynak dosyanızı kaydedin; metin düzenleyiciniz muhtemelen UTF-8 kullanacak şekilde yapılandırılmıştır, bu nedenle dize hazır bilginiz diskte UTF-8 olarak kodlanır. PHP dizeyi bir bayt dizisi olarak yorumlayarak bu dosyayı okur; $originalşimdi sadece bir bayt dizisi olan 7 karakterden oluşan UTF-8 kodlu bir dizeye sahiptir (her karakter iki veya daha fazla bayt ile temsil edildiğinden, 7 bayttan fazlasını içermesine rağmen). Daha sonra ararsanız echo $original, kodlanmış dize istemciye olduğu gibi gönderilir; istemciye UTF-8'i beklemesini söylediyseniz, her şey yolundadır, ancak yapmadıysanız, PHP'nin farkı söylemenin bir yolu yoktur ve tarayıcıda çöp ile sonuçlanırsınız. Bir deneme olarak şunu deneyin:

$original = "शक्नोम्यत्तुम्";
echo strlen($original);

strlen kodlama-agnostiktir ve sabit genişlikli 8 bit kodlamayı, yani karakter başına bir bayt olduğunu varsayar, böylece karakterleri değil baytları sayacaktır.


Yani dönüştürülmüş $ aynı dizeyi temsil eder, ancak diğer kodlamada. PhP deposu olan gerçek ham kodlama farklı olacaktır.
user4951

2
Bunu sizin için tekrarlayacağım: PHP karakterleri değil, baytları depolar ve kodlamalar hakkında hiç bir şey bilmez (bazı kütüphane işlevleri olsa da.
tdammers

1
Oh, ve bu "PHP", "PhP" değil.
tdammers

2
ham baytlar aynıysa, $ original ve $ converted arasındaki fark nedir? Sorduğum şey bu.
user4951

2
Oh, tamam, demek istediğin bu. Evet, ham baytlar kodlama dönüşümüne göre değişir. PHP kodlamayı hatırlamıyor, bu yüzden bir dizeyi örneğin diyelim ki utf-8'den latin-1'e dönüştürür ve sonucu utf-8 olarak ele alırsanız garip sonuçlar görürsünüz.
tdammers
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.