2013-07-09 17 views
5

Mam bazę danych, która przechowuje nazwy gier wideo ze znakami Unicode, ale nie mogę się dowiedzieć, jak poprawnie uciec przed znakami Unicode podczas drukowania ich w odpowiedzi HTML.Drukowanie znaków Unicode PHP

Na przykład, kiedy wydrukować wszystkie gry z nazwą jak Uncharted, otrzymuję to:

Uncharted: Drake's Fortuneâ„¢ 
Uncharted 2: Among Thievesâ„¢ 
Uncharted 3: Drake's Deceptionâ„¢ 

ale powinien wyświetlić ten:

Uncharted: Drake's Fortune™ 
Uncharted 2: Among Thieves™ 
Uncharted 3: Drake's Deception™ 

Pobiegłem szybko funkcję escape JavaScript do zobacz, który znak Unicode jest i okazało się, że jest to \u2122.

Nie mam problemu z całkowitym odskoczeniem każdego znaku w ciągu znaków, jeśli mogę poprawnie wyświetlić znak . Domyślam się jakoś odnaleźć reprezentację hex każdego znaku w łańcuchu i mają PHP czyni znaki Unicode, takie jak ten:

print "&#x2122"; 

proszę kierować do mnie poprzez najlepszego podejścia do ucieczki ciąg Unicode dla bycia HTML obsłudze. Zrobiłem coś podobnego dla JavaScript jakiś czas temu, ale JavaScript ma wbudowaną funkcję ucieczki i unescape.

Nie znam jednak żadnych funkcji PHP o podobnej funkcjonalności. Przeczytałem o funkcji ord, ale po prostu zwraca kod znaków ASCII dla danego znaku, a tym samym niewłaściwe wyświetlanie ™ lub ™. Chciałbym, aby ta funkcja była wystarczająco uniwersalna, aby zastosować ją do dowolnego łańcucha zawierającego prawidłowe znaki Unicode.

Odpowiedz

14

Wygląda jak masz ciągi UTF-8 zakodowane wewnętrznie, PHP wyprowadza je prawidłowo, ale Twoja przeglądarka nie automatycznie wykrywa kodowanie (to decyduje o ISO 8859-1 lub innym kodowaniu).

Najlepszym sposobem jest poinformować przeglądarkę, że UTF-8 jest używany wysyłając odpowiedni nagłówek HTTP:

header("content-type: text/html; charset=UTF-8"); 

Następnie można zostawić resztę kodu jak jest i don nie muszą kodować encji html lub tworzyć innego bałaganu.

Jeśli chcesz, możesz dodatkowo deklarować kodowanie w HTML wygenerowany za pomocą <meta> tag:

  • <meta http-equiv=Content-Type content="text/html; charset=UTF-8"> HTML < = 4,01
  • <meta charset="UTF-8"> dla HTML5

Nagłówek HTTP ma wyższy priorytet niż znacznik <meta>, ale ten drugi może być przydatny, jeśli kod HTML zostanie zapisany w HD, a następnie odczytany w locie sprzymierzyć.

9

Spędziłem dużo czasu próbując znaleźć lepszy sposób, aby wydrukować równoważny kod kodu unicode, a metody, które znalazłem, nie działały lub po prostu były bardzo skomplikowane.

Ten powiedział, JSON jest w stanie reprezentować unicode znaków za pomocą składni "\ u [unicode_code]", a następnie:

echo json_decode('"\u00e1"'); 

wypisze równoważne unicode char, w tym przypadku: a.

P.D. Zwróć uwagę na proste i podwójne cudzysłowy. Jeśli nie włożysz obu, to nie zadziała.

1
// PHP 7.0 
var_dump(
    IntlChar::chr(0x2122), 
    IntlChar::chr(0x1F638) 
); 

var_dump(
    utf8_chr(0x2122), 
    utf8_chr(0x1F638) 
); 

function utf8_chr($cp) { 

    if (!is_int($cp)) { 
     exit("$cp is not integer\n"); 
    } 

    // UTF-8 prohibits characters between U+D800 and U+DFFF 
    // https://tools.ietf.org/html/rfc3629#section-3 
    // 
    // Q: Are there any 16-bit values that are invalid? 
    // http://unicode.org/faq/utf_bom.html#utf16-7 

    if ($cp < 0 || (0xD7FF < $cp && $cp < 0xE000) || 0x10FFFF < $cp) { 
     exit("$cp is out of range\n"); 
    } 

    if ($cp < 0x10000) { 
     return json_decode('"\u'.bin2hex(pack('n', $cp)).'"'); 
    } 

    // Q: Isn’t there a simpler way to do this? 
    // http://unicode.org/faq/utf_bom.html#utf16-4 
    $lead = 0xD800 - (0x10000 >> 10) + ($cp >> 10); 
    $trail = 0xDC00 + ($cp & 0x3FF); 

    return json_decode('"\u'.bin2hex(pack('n', $lead)).'\u'.bin2hex(pack('n', $trail)).'"'); 
} 
Powiązane problemy