Imprimă caractere Unicode PHP (Programare, Php, Unicode, Caractere De Scăpare Html)

Cameron Tinker a intrebat.

Am o bază de date care stochează nume de jocuri video cu caractere Unicode, dar nu-mi pot da seama cum să scap în mod corespunzător de aceste caractere Unicode atunci când le tipăresc într-un răspuns HTML.

De exemplu, atunci când tipăresc toate jocurile cu numele de genul Uncharted, obțin acest lucru:

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

dar ar trebui să se afișeze așa:

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

Am rulat o funcție rapidă de evadare JavaScript pentru a vedea ce caracter Unicode se este și am constatat că este u2122.

Nu am o problemă în a scăpa complet fiecare caracter din șir dacă pot obține caracterul să se afișeze corect. Bănuiala mea este să găsesc cumva reprezentarea hexagonală a fiecărui caracter din șir și să fac ca PHP să redea caracterele Unicode astfel:

print "&#x2122";

Vă rog să mă ghidați prin cea mai bună abordare pentru ca Unicode să evadeze un șir pentru a fi prietenos cu HTML. Am făcut ceva similar pentru JavaScript cu ceva timp în urmă, dar JavaScript are o funcție încorporată pentru escape și unescape.

Nu am cunoștință de nicio funcție PHP cu funcționalitate similară însă. Am citit despre ord dar aceasta returnează doar codul ASCII pentru un anumit caracter, de unde și afișarea necorespunzătoare a caracterului ™ sau a caracterului ™. Aș dori ca această funcție să fie suficient de versatilă pentru a se aplica oricărui șir de caractere care conține caractere Unicode valide.

4 răspunsuri
Alex Shesterov

Se pare că aveți șiruri codificate UTF-8 în mod intern, PHP le afișează corect, dar browserul dvs. nu reușește să detecteze automat codificarea (se decide pentru ISO 8859-1 sau o altă codificare).

Cea mai bună metodă este să spuneți-i browserului că se utilizează UTF-8 prin trimiterea antetului HTTP corespunzător:

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

Apoi, puteți lăsa restul codului dumneavoastră așa cum este și nu trebuie să codificați entitățile în html sau să creați alte probleme.

Dacă doriți, puteți în plus să declarați codificarea în HTML-ul generat, utilizând opțiunea de codare <meta> tag:

  • <meta http-equiv=Content-Type content="text/html; charset=UTF-8"> pentru HTML <=4.01
  • <meta charset="UTF-8"> pentru HTML5

antetul HTTP are prioritate față de antetul <meta> dar acesta din urmă poate fi util în cazul în care HTML-ul este salvat pe HD și apoi citit local.

Comentarii

  • @ViktorJoras verificați dacă scripturile PHP și/sau resursele de șiruri de caractere de pe server sunt codificate UTF-8. –  > Por Alex Shesterov.
sh4

Am petrecut mult timp încercând să găsesc o modalitate mai bună de a imprima pur și simplu caracterul echivalent al unui cod unicode, iar metodele pe care le-am găsit nu au funcționat sau au fost foarte complicate.

Acestea fiind spuse, JSON este capabil să reprezinte caractere unicode folosind sintaxa „u[unicode_code]”, apoi:

echo json_decode('"u00e1"'); 

Va imprima caracterul unicode echivalent, în acest caz: á.

P.D. Observați ghilimelele simple și duble. Dacă nu le puneți pe amândouă, nu va funcționa.

CXJ

Încercați acest lucru:

echo htmlentities("Uncharted: Drakes Fortune™ 
", ENT_QUOTES, "UTF-8");

De la: http://php.net/htmlentities

masakielastic
// 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
");
    }

    // 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
");
    }

    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)).'"');
}