web-dev-qa-db-fra.com

Caractère Unicode dans la chaîne PHP

Cette question a l'air d'une simplicité embarrassante, mais je n'ai pas réussi à trouver de réponse.

Qu'est-ce que PHP équivaut à la ligne de code C # suivante?

string str = "\u1000";

Cet exemple crée une chaîne avec un seul caractère Unicode dont la "valeur numérique Unicode" est 1000 en hexadécimal (4096 en décimal).

En PHP, comment puis-je créer une chaîne avec un seul caractère Unicode dont la "valeur numérique Unicode" est connue?

141
Telaclavo

Comme JSON prend directement en charge la syntaxe \uxxxx, la première chose qui me vient à l’esprit est la suivante:

$unicodeChar = '\u1000';
echo json_decode('"'.$unicodeChar.'"');

Une autre option serait d'utiliser mb_convert_encoding()

echo mb_convert_encoding('က', 'UTF-8', 'HTML-ENTITIES');

ou utilisez le mappage direct entre UTF-16BE (big endian) et le codepoint Unicode:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');
163
Stefan Gehrig

PHP 7.0.0 a introduit la syntaxe "Unicode codointpoint escape" .

Il est maintenant possible d'écrire facilement des caractères Unicode en utilisant une chaîne guillemets doubles ou heredoc , sans appeler de fonction.

$unicodeChar = "\u{1000}";
121
Blackhole

PHP ne connaît pas ces séquences d'échappement Unicode. Mais comme les séquences d'échappement inconnues ne sont pas affectées, vous pouvez écrire votre propre fonction qui convertit ces séquences d'échappement Unicode:

_function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}
_

Ou avec un expression de fonction anonyme au lieu de create_function :

_function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', function($match) use ($encoding) {
        return mb_convert_encoding(pack('H*', $match[1]), $encoding, 'UTF-16BE');
    }, $str);
}
_

Son utilisation:

_$str = unicodeString("\u1000");
_
20
Gumbo

Je me demande pourquoi personne n'en a encore parlé, mais vous pouvez faire une version presque équivalente en utilisant des séquences d'échappement dans chaînes entre guillemets :

\x[0-9A-Fa-f]{1,2}

La séquence de caractères correspondant à l'expression régulière est un caractère en notation hexadécimale.

Exemple ASCII:

<?php
    echo("\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21");
?>

Bonjour le monde!

Donc, dans votre cas, tout ce que vous avez à faire est de $str = "\x30\xA2";. Mais ce sont octets , pas des caractères. La représentation en octets du code codé Unicode coïncide avec le big endian UTF-16. Nous pouvons donc l’imprimer directement en tant que tel:

<?php
    header('content-type:text/html;charset=utf-16be');
    echo("\x30\xA2");
?>

Si vous utilisez un codage différent, vous devrez modifier les octets en conséquence (la plupart du temps avec une bibliothèque, bien que cela soit aussi possible à la main).

Exemple little endian UTF-16:

<?php
    header('content-type:text/html;charset=utf-16le');
    echo("\xA2\x30");
?>

Exemple UTF-8:

<?php
    header('content-type:text/html;charset=utf-8');
    echo("\xE3\x82\xA2");
?>

Il existe également la fonction pack , mais vous pouvez vous attendre à ce qu'elle soit lente.

19
Pacerier
html_entity_decode('&#x30a8;', 0, 'UTF-8');

Cela fonctionne aussi. Cependant, la solution json_decode () est beaucoup plus rapide (environ 50 fois).

8
flori

Essayez Portable UTF-8 :

$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );

Tous fonctionnent exactement de la même manière. Vous pouvez obtenir le code d'un personnage avec utf8_ord(). En savoir plus sur Portable UTF-8 .

7
Hamid Sarfraz

Comme d'autres l'ont mentionné, PHP 7 introduit directement le support de la syntaxe \u Unicode.

Comme cela a également été mentionné par d’autres, le seul moyen d’obtenir une valeur de chaîne à partir de toute description de caractère Unicode sensible en PHP consiste à le convertir à partir de quelque chose d’autre (par exemple, analyse JSON, analyse HTML ou autre). Mais cela a un coût de performance d'exécution.

Cependant, il existe une autre option. Vous pouvez encoder le caractère directement dans PHP avec \x échappement binaire. La syntaxe d'échappement \x est également prise en charge dans PHP 5.

Ceci est particulièrement utile si vous préférez ne pas saisir le caractère directement dans une chaîne par le biais de sa forme naturelle. Par exemple, s’il s’agit d’un caractère de contrôle invisible ou d’un autre élément difficile à détecter.

Tout d'abord, un exemple de preuve:

// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = "&#8202;";
$realChar = html_entity_decode($htmlEntityChar);
$phpChar = "\xE2\x80\x8A";
echo 'Proof: ';
var_dump($realChar === $phpChar); // bool(true)

Notez que, comme le mentionnait Pacerier dans une autre réponse, ce code binaire est unique pour un codage de caractères spécifique. Dans l'exemple ci-dessus, \xE2\x80\x8A est le codage binaire pour U + 200A en UTF-8.

La question suivante est de savoir comment aller de U+200A à \xE2\x80\x8A?

Vous trouverez ci-dessous un script PHP permettant de générer la séquence d'échappement de tout caractère, en fonction d'une chaîne JSON, d'une entité HTML ou de toute autre méthode une fois que vous l'avez sous forme de chaîne native.

function str_encode_utf8binary($str) {
    /** @author Krinkle 2018 */
    $output = '';
    foreach (str_split($str) as $octet) {
        $ordInt = ord($octet);
        // Convert from int (base 10) to hex (base 16), for PHP \x syntax
        $ordHex = base_convert($ordInt, 10, 16);
        $output .= '\x' . $ordHex;
    }
    return $output;
}

function str_convert_html_to_utf8binary($str) {
    return str_encode_utf8binary(html_entity_decode($str));
}
function str_convert_json_to_utf8binary($str) {
    return str_encode_utf8binary(json_decode($str));
}

// Example for raw string: Unicode Character 'INFINITY' (U+221E)
echo str_encode_utf8binary('∞') . "\n";
// \xe2\x88\x9e

// Example for HTML: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_html_to_utf8binary('&#8202;') . "\n";
// \xe2\x80\x8a

// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a
1
Timo Tijhof