- Inscription
Langue : [automatic], [fr], [en], … | Allez on remonte !
Information : Inscris-toi ou connecte-toi pour pouvoir participer aux forums d'Olissea.
Liste des BBS :
[PHP] [MySQL] Stocker UTF-8 avant MySQL 5.5 (sans utf8mb4) ?
Page 1 / 1
JeromeJ
[Avatar de JeromeJ]
posté le 03/05/2014 à 6h11
Légende vivante
[Message déjà lu]
Helloooo


Quelqu'un aurait-il une idée afin de stocker de l'UTF-8 façon correcte avec MySQL d'une version antérieur à MySQL 5.5 ?

Background: Avant MySQL5.5, il n'y a que l'option utf8 et non l'option utf8mb4 permettant (enfin!) de stocker des caractères codés sur 4 bytes ("I wish I was kidding" - Source ).

What I've tried so far / Ce que j'ai déjà essayé :

J'avais pensé à peut-être utilisé un champ de type BINARY (ou BLOB), ce qui me permettrait d'y stocker ce que j'y veux (le problème serait donc résolu) mais cela apporte aussi son lot d'inconvénients…

- Memory overhead pour accéder à des champs de type TEXT ou BLOB. (Boarf, pas très grave, j'utilise déjà un champ TEXT)
- Impossibilité d'utiliser ses champs dans une clause WHERE et donc, je suppose, également dans un LIKE afin de faire une recherche dans la base de données. Right?

(J'aurais du garder les sources parlant de ces dits inconvénients… sorry)

Côté PHP je pourrais essayer de détecter les caractères sur 4 bytes (ça serait lourd par contre) mais j'ignore même ce que j'en ferais… Les convertir en entité HTML ?
Je refuse de me mettre à utiliser htmlentities au lieu d'htmlspecialchars :( (fin, ça serait trop triste quoi)
------------------------------------------
"Olissea en force | (╯°□°)╯︵ ┻━┻ Hmm… ಠ_ಠ | Vertuous circles ☺"
JeromeJ
[Avatar de JeromeJ]
posté le 04/05/2014 à 18h26
Légende vivante
[Message déjà lu]
Plop.

Après mainte péripéties et échecs, je pense avoir trouver quelque chose de "potable".

Voir le code avec coloration syntaxique (un peu différent, manque une source)

<?php

# "😒" est codé sur 4 bytes
$body = 'lol😒a☺';

echo 'before: ',$body,'<br />'; # Output: lol😒a☺
echo 'length: ',strlen($body),'<br />'; # Output: 11 (😒 = 4, ☺ = 3)

# Le but est de remplacer uniquement les caractères de plus de 3 bytes par leur entité HTML.
# Afin d'obtenir ce code dans le cas de notre exemple
echo '&#x1F612;','<br />'; # Fourni par https://duckduckgo.com/?q=html+%F0%9F%98%92

# Récupération des caractères de plus de 3 bytes uniquement
# Source: http://stackoverflow.com/a/1401716/1524913
# $body = preg_replace('/[\xF0-\xF7][\x80-\xBF]{3}/', '�', $body); # Yeah! It works!

# Ne fonctionne pas. htmlentities ne connaît pas tous les caractères unicode ( http://stackoverflow.com/a/13942507/1524913 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return htmlentities($m[0], ENT_COMPAT, 'UTF-8');}, $body); # Ignore complètement 😒

# La solution proposée au lien précédemment cité : Ne fonctionne pas non plus
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return str_replace('\\u','&#x',trim(json_encode($m[0]),'"')).';';}, $body);
# Output: lol��a☺ car json_encode considère ça comme deux caractères de deux bytes et renvoie "\ud83d\ude12"

# Ne fonctionne pas ( http://php.net/manual/en/function.htmlentities.php#107985 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_encode_numericentity($m[0], array(0x0, 0xffff, 0, 0xffff), 'UTF-8');}, $body); # Ignore complètement 😒

# Fonctionne !!! Mais renvoie &#128530 au lieu de &#x1F612; (Pas vraiment un problème en soit)
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8');}, $body);

# Si on veut vraiment la version hexadécimal
$body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return '&#x'.dechex(substr(mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8'), 2)).';';}, $body);

echo 'after: ',$body,'<br />'; # Output: lol&#x1f612;a☺

?>

EDIT: Désolé, je ne peux pas utiliser la coloration syntaxique car, n'ayant pas encore implémenté cette solution, j'ai activé l'HTML pour ce message (creator only) mais la balise code me l'échappe si je tente de faire ça. :)

EDIT: J'ai trouvé ce problème ceci dit: https://bugs.php.net/bug.php?id=65045
Mais j'ignore si je suis vraiment concerné : ça dépend en effet si mon script capture ces séquences à problèmes mais il me semble qu'il ne capture que les séquences valides de 4 bytes, donc pas de problème normalement.

Également, j'ai pas trop compris comment ça se fait, mais lorsque j'applique htmlspecialchars sur les séquences données sur la page, l'output n'est pas vide. Ne devrait-il pas l'être (vu que htmlspecialchars renvoie stupidement une chaîne vide lorsqu'il reçoit de l'UTF-8 invalide normalement ?).

Mmmmmh.
------------------------------------------
"Olissea en force | (╯°□°)╯︵ ┻━┻ Hmm… ಠ_ಠ | Vertuous circles ☺"
Page : 1
Répondre au sujet
Réponse rapide :