Ben doğru benim PHP apps UTF-8 destekleyen muyum?

5 Cevap php

Ben UTF-8 hakkında bilmek her şeyin doğru olduğundan emin olmak istiyorum. Ben şimdi bir süre için UTF-8 kullanmak için çalışıyorlar ama ben daha çok böcek ve% 100 UTF-8 sitesine sahip olmak neredeyse imkansız görünüyor yapmak diğer garip şeyler karşısında tökezleyerek devam. Ben kaçırmak gibi bir yakaladım yerde her zaman vardır. Belki burada birisi bu yüzden önemli bir şey kaçırmayın listemi veya Tamam düzeltebilirsiniz.

Database

Her sitenin bir yerde orada veri depolamak için vardır. Olursa olsun PHP ayarlarının ne de DB yapılandırmanız gerekir. Eğer yapılandırma dosyalarını erişemiyorsanız sonra emin olmak için "SET NAMES 'utf8'" olarak takmaz. Ayrıca, tüm tabloları üzerinde utf8_ unicode_ ci kullandığınızdan emin olun. Bu veritabanı için MySQL varsayar, başkaları için değiştirmek zorunda kalacak.

Regex

Ben ortalama arama yerine daha more complex olan regexdeki bir sürü yapmak. Ben böylece "/ u" değiştirici kullanmak hatırlamak zorunda PCRE doesn't corrupt my strings. Yine de, hatta daha sonra orada still problems apparently.

String Functions

(Vs strlen (), strpos ()) varsayılan dize tüm fonksiyonları yerine byte karakter bakmak Multibyte String Functions Bunun değiştirilmesi gerekir.

Headers You should make sure that your server is returning the correct header for the browser to know what charset you are trying to use (just like you must tell MySQL).

header('Content-Type: text/html; charset=utf-8');

Bu doğru koymak için de iyi bir fikirdir < meta> sayfa kafasına etiketi. Gerçek başlık bu geçersiz olacak olsa da farklı olmalıdır.

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

Questions

Ben UTF-8 için kullanıcı aracısı (HTML form en & URI) aldığınız her şeyi dönüştürmek için gereken ne zaman, sayfa yüklenirken veya onlar gibi sadece dizeleri / değerleri bırakmak ve hala olmadan bu fonksiyonlar aracılığıyla çalıştırabilirsiniz eğer Sorun?

Ben UTF-8 için her şeyi dönüştürmek için ihtiyacınız yoksa - o zaman ne adımlar atmalıyım? mb_detect_encoding Bunun için inşa edilecek gibi görünüyor ama insanlar her zaman çalışmıyor şikayetçi görmeye devam. mb_check_encoding, aynı zamanda bozuk bir iyi bir UTF-8 dizesi söylüyorum bir sorun var gibi görünüyor.

Does PHP store strings in memory differently depending on what encoding it is using (like file types) or is it still stored like a regular sting with some of the chars being interpreted differently (like & amp; vs & in HTML). chazomaticus Bu soru cevaplar:

In PHP (up to PHP5, anyway), strings are just sequences of bytes. There is no implied or explicit character set associated with them; that's something the programmer must keep track of.

A MB_ * işlevi olmayan bir UTF-8 dizesi verirseniz hiç bir sorun neden olur?

UTF dize yanlış kodlanmış ise irade şey (? Regex bir ayrıştırma hatası gibi) yanlış ya da sadece kötü bir varlık (html) işaretlemek olacak? Yanlış kodlanmış dizeleri dize kötü çünkü işlev FALSE dönen neden olacak bir şans hiç var mı?

Ben size de UTF-8 olarak oluşturur (accept-charset = "UTF-8") ama yararı nedir emin değilim işaretlemek gerektiğini duydum ..?

UTF-16 UTF-8 bir sınırı gidermek için yazılmıştır? Gibi karakterler için dışarı alanı UTF-8 run mi? (Y2 (UTF) k?)

Functions

İşte ben buldum ama onlar aslında çalışmaya doğrulamak için herhangi bir şekilde değil olması özel PHP işlevlerinin bir çift vardır. Belki birisi ben kullanabileceğiniz bir örnek vardır. İlk convertToUTF8() ve daha sonra wordpress gelen seems_utf8.

function seems_utf8($str) {
    $length = strlen($str);
    for ($i=0; $i < $length; $i++) {
        $c = ord($str[$i]);
        if ($c < 0x80) $n = 0; # 0bbbbbbb
        elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
        elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
        elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
        elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
        elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
        else return false; # Does not match any model
        for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
            if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
                return false;
        }
    }
    return true;
}

function is_utf8($str) {
    $c=0; $b=0;
    $bits=0;
    $len=strlen($str);
    for($i=0; $i<$len; $i++){
        $c=ord($str[$i]);
        if($c > 128){
            if(($c >= 254)) return false;
            elseif($c >= 252) $bits=6;
            elseif($c >= 248) $bits=5;
            elseif($c >= 240) $bits=4;
            elseif($c >= 224) $bits=3;
            elseif($c >= 192) $bits=2;
            else return false;
            if(($i+$bits) > $len) return false;
            while($bits > 1){
                $i++;
                $b=ord($str[$i]);
                if($b < 128 || $b > 191) return false;
                $bits--;
            }
        }
    }
    return true;
}

Herkes ilgi ise ben kullanmak için harika bir örnek sayfa bulunamadı when testing UTf-8.

5 Cevap

Ben UTF-8 için kullanıcı aracısı (HTML form en & URI) aldığınız her şeyi dönüştürmek için gereken ne zaman sayfa yüklendiğinde

Hayır kullanıcı aracısı UTF-8 formatında veri göndererek olmalıdır; eğer değil Unicode yarar kaybediyor.

Bir user-agent sağlamak için yol UTF-8 biçiminde gönderir UTF-8 kodlamasıyla göndermek gibi form içeren sayfa hizmet etmektir. (Eğer kaydedilecek formu ve çalışma Bağımsız niyetinde eğer çok ve meta http-eşlenik) Content-Type başlığı kullanın.

Ben size gibi formları işaretlemek gerektiğini duydum UTF-8 de (accept-charset = "UTF-8")

Don't. Bu HTML standardında güzel bir fikirdi, ama IE sağ asla var. Bu izin verilen karakter setlerinin özel bir liste devlet gerekiyordu, ancak IE başına alan bazında, denemek için ek karakter setlerinin listesi gibi davranır oldu. Eğer bir ISO-8859-1 sayfa ve varsa Yani "kabul-charset =" UTF-8 "," formu, IE ilk ISO-8859-1 gibi bir alan kodlamak için çalışacağız, ve bir non-8859-1 varsa karakter orada, then UTF-8 başvurmak gerekir.

IE ISO-8859-1 veya UTF-8 kullanılır olup olmadığını size değil çünkü Ama, bu sizin için kesinlikle hiçbir faydası bulunuyor. Kullanımda olan kodlama, ayrı ayrı her bir alan için, tahmin etmek olurdu! Kullanışlı değil. Özniteliği atlarsanız ve UTF-8 olarak sayfalarını hizmet; size şu anda yapabileceğiniz en iyisidir.

UTF dize yanlış kodlanmış ise irade terslik

Eğer böyle bir dizi tarayıcısı yoluyla almak izin eğer sorun olabilir. Gerekli olandan daha uzun bir bayt sırayla bir düşük numaralı kodlaması altında kodlayan 'aşırı-diziler bulunmaktadır. Bu filtreleme eğer gelir '<' bayt dizisi bu ASCII karakter için bakarak, birini kaçırmayın olabilir ve güvenli bir metin olduğunu düşündüğüm bir komut dosyası öğesini edelim.

Overlong dizileri Unicode ilk günlerinde geri yasaklandı, ancak kendi bok birlikte almak için Microsoft bir çok uzun bir zaman aldı: IE a '<' yukarıya kadar IE6 Service Pack 1 olarak bayt dizisi '\ xC0 XBC \' ​​yorumlamak istiyorum . Opera sürümünde de 7 (sanırım yaklaşık). Neyse ki bu eski tarayıcılar dışarı ölüyor kadar yanlış var, ama bu tarayıcılar hakkında şimdi hala (ya da yeni aptal tarayıcılar içinde aynı hatayı yapmak durumunda overlong dizileri filtreleme hala değer gelecek). Bunu yapmak, ve bu tür W3 gelen this one olarak sadece uygun UTF-8 ile sağlayan bir regex, ile, diğer kötü dizileri çözebilirsiniz.

Eğer PHP MB_ fonksiyonları kullanarak, size might bu konularda izole edilebilir. Ben hala PHP yazarken MB_ * kullanılamaz kırılgan olarak emin diyemem.

Her durumda, bu da hataların büyük ve genellikle hesaba katılmayan kaynağıdır kontrol karakterleri kaldırmak için iyi bir zaman. Ben W3 regex dışarı alır diğerlerine ek olarak sunulan dizeden karakter 9 ve 13 kaldırmak istiyorsunuz; o da bildiğiniz dizeleri düz satırsonlarını çıkarmadan değer satırlı metin kutularının olması gerekiyordu değildir.

UTF-16 UTF-8 bir sınırı gidermek için yazılmıştır?

Hayır, UTF-16 Unicode her iki byte uyabilecek zaman gün (in-memory indeksleme Unicode dizeleri kolaylaştırmak için kullanılan bir iki bayt başına codepoint kodlama, Windows ve Java gibi sistemler hala yapmak bu şekilde .) UTF-8 aksine ASCII ile uyumlu değildir, ve Web üzerinde az-hiçbir faydası yoktur. Ama zaman zaman, kaydedilen dosyaları kaydetmek-menülerde "Unicode" olarak UTF-16LE Windows açıklamasında tarafından yanıltılmış Windows kullanıcıları tarafından kaydedilen genellikle olanları bunu karşılamak.

seems_utf8

Bu regex göre çok verimsiz!

Ayrıca, tüm tabloları üzerinde utf8_unicode_ci kullandığınızdan emin olun.

Aslında tür bayt ama hiçbir şey için bir mağaza olarak MySQL tedavi ve sadece komut UTF-8 olarak yorumlayarak, bu olmadan uzak alabilirsiniz. Utf8_unicode_ci kullanmanın avantajı, çok örneğin, non-ASCII karakter hakkında bilgi ile (harf duyarsız karşılaştırır sıralama ve mutlaka) toplayacaktır olmasıdır. 'R' ve 'r' aynı karakter vardır. Olmayan bir UTF8 harmanlamayı kullanmak eğer ikili (harf duyarlı) eşleştirme ayrılmamak gerekir.

Hangisini seçerseniz seçin, bu sürekli yapın: Eğer bağlantı için ne gibi tablolar için aynı karakter setini kullanabilirsiniz. Ne kaçınmak istediğiniz scriptler ve veritabanı arasında bir kayıplı karakter kümesi dönüşüm.

Şimdi ne yapıyorsun en doğru olmalıdır.

Bazı notlar: MySQL herhangi bir utf_* harmanlama UTF-8 olarak doğru veri depolamak, aralarındaki tek fark sıralarken harmanlama (alfabetik sırayla) uygulanan.

Sırasıyla php.ini içinde httpd.conf / .htaccess ve default_charset = "utf-8" in AddDefaultCharset utf-8 ayarını doğru charset başlıkları vermek için Apache ve PHP söyleyebilirim.

Sen string fonksiyonları dikkat çekmek için mbstring uzantısı söyleyebilirim. Bu benim için çalışıyor:

mbstring.internal_encoding=utf-8
mbstring.http_output=UTF-8
mbstring.encoding_translation=On
mbstring.func_overload=6

Fonksiyonu bakir (bu mail( yaprak) - benim posta başlıkları ile tahribat oynanan 7'ye ayarlama bulundu)

Charset dönüşüm için https://sourceforge.net/projects/phputf8/ bakabilirsiniz.

PHP, değişken içinde ne hakkında umurumda sadece mağaza ve körü körüne içeriğini alır almaz.

Eğer başka bir kodlama bir MB_ * fonksiyonu dizeleri bir mbstring.internal_encoding arz ve beyan eğer beklenmedik sonuçlar elde edeceksiniz. Zaten güvenle utf-8 işlevlerine ASCII gönderebilirsiniz.

Eğer birileri kasten yanlış kodlanan şeyler gönderme konusunda endişeli iseniz ben işlemeden önce GET / POST verileri filtrelemek için HTML Purifie r ele almamız inanıyorum.

Accept-charset sonsuza dek beri gözlük olmuştur, ancak tarayıcılarda gerçek dünya destek sıfır veya daha az olan vardır. Tarayıcı tipically formu içeren sayfayı af kodlamasını kullanır.

UTF-16 UTF-8 büyük kardeşi değil, sadece farklı bir amaca hizmet eder.

database/mysql: If you're using SET NAMES and e.g. php/mysql you're leaving mysql_real_escape_string() in the dark about the change in character encoding. This may lead to wrong results. So, if you're relying on an escape function like mysql_real_escape_string (because you're not using prepared statements) SET NAMES is a suboptimal solution. That's why mysql_set_charset() has been introduced or why gentoo applies a patch that adds the config parameter mysql.connect_charset for both php/mysql and php/mysqli.

İstemci genellikle gönderir parametreleri kodlama göstermez. Eğer utf-8 kodlanmış verileri and treat it as such hataları (utf-8 geçersiz bayt dizileri) orada kodlayan olabilir bekliyoruz. Yani beklendiği gibi verileri görüntüleyebilir olmayabilir veya bir ayrıştırıcı ayrıştırma iptal edebilir. Ama en azından kullanıcı girişi "kaçış" ve daha fazla zarar örneğin yapamam Bir satır içi sql deyimi veya html çıktı. Örneğin (iso-8859-1 ya da utf-8, farketmez olarak kaydedilir) komut dosyasını almak

<?php
$s = 'abcxyz';
var_dump(htmlspecialchars($s, ENT_QUOTES, 'utf-8'));
// adding the byte sequence for äöü in iso-8859-1
$s = 'abc'. chr(0xE4) . chr(0xF6) . chr(0xFC). 'xyz';
var_dump(htmlspecialchars($s, ENT_QUOTES, 'utf-8'));

baskılar

string(6) "abcxyz"
string(0) ""

E4F6FC nedenle htmlspecialchars'ın boş bir dize döndürür, geçerli bir utf-8 bayt sırası değil. Diğer fonksiyonlar geri dönebilir? ya da başka bir "özel" bir karakter. Ama en azından onlar kötü niyetli bir denetim karakteri olarak "hata" bir karakter olmaz - sürece hepsi "doğru" kodlaması (bu durumda utf-8) için sopa gibi.

accept-charset bu kodlama ile sadece veri alacağı garanti etmez. Eğer müşteri bile "kullanılan" vardır olmayabilir biliyorum tüm / form öğesi içeren html belge çözümlü. Bu yardımcı olabilir ve bu özniteliği ayarlamak değil hiçbir neden yok. Ama bu "güvenilir" değil.

UTF-8 ince ve UTF-16 çözer herhangi sınırları yoktur. PHP değişiklikleri (Python aksine) bellekte dizeleri depolamak için yol doens't. Tüm veri akışı UTF-8 kullanıyorsa (web formları, tabloları utf8 kodlaması kullanın ve SET NAMES utf8 kullanıyorsanız, ve veri) (hiçbir karakter dönüşümünü değişmiş olmadan saklanır, UTF-8 veri almak Bu ince olmalıdır.

Formdan kullanıcı girişleri için benim form s etiketleri için bu niteliği ekleyin: accept-charset="utf-8". Aldığınız bu şekilde veri should her zaman utf-8 olarak kodlanmış.