作成日:2023-07-20, 更新日:2023-08-10
mySQLの「utf8」
utf8は基本、4バイト。でもmySQLでは3バイト。
mySQLの4バイトのutf8は「utf8mb4」ってヤツ。
mySQLでの型
- utf8 - 3バイト(utf8mb3と同じ)
- utf8mb4 - 4バイト
- utf8mb3 - utf8と同じ(3バイト)
「utf8」→「utf8mb4」
いろいろと調べると…MySQLの文字コードを「utf8」から「utf8mb4」に変更すればいいとのコト
パターンとしては下記の3種類かと。
- DB自体を「utf8mb4」にする
- 対象テーブルのみ「utf8mb4」にする
- 対象カラムのみ「utf8mb4」にする
特別な理由が無ければDBの文字コードを「utf8mb4」にするのが良さげ
文字化けするとき
「utf8mb4」にしても状況によっては文字化けすることがあるらしい。
そのときはinsert前にutf8mb4に追加してやれば良いとのトコ
▼PHP側でinsertする前に下記実行
set names utf8mb4
「utf8」→「binary」
対象カラムのみ「binary」にしてみたが…よくわからんが…ダメだった
DBをutf8mb4にすればいけるかもしれないし、特定の絵文字がダメだったかもしれない。未調査
「utf8」のままで保存
絵文字…というか文字をunicodeに変換してDBに保存する…という方針
一文字だけ
以下は、「絵文字一文字だけ」でもunicodeにすると2文字になる場合があるので、実質使えない…
$emoji = '😢'; $unicode_emoji = base_convert(bin2hex(mb_convert_encoding($emoji, 'UTF-32BE', 'UTF-8')), 16, 16); // ▼絵文字に戻す // echo mb_convert_encoding(hex2bin(str_repeat('0', 8 - strlen($unicode_emoji)).$unicode_emoji), 'UTF-8', 'UTF-32BE'); // echo '' . $unicode_emoji . ';' // 絵文字に戻すならコッチでも良いような気がする
文字列
$emoji = '😢だよ'; $length = mb_strlen($emoji); $unicode_many = []; $conv_emoji = mb_convert_encoding($emoji, 'UTF-32BE', 'UTF-8'); for ($i = 0; $i < $length; ++$i) { $tmp_unicode = mb_substr(conv_emoji, $i, 1, 'UTF-32BE'); $unicode_many[$i] = base_convert(bin2hex($tmp_unicode), 16, 16); }
unicodeを文字列に戻す
文字に戻すなら上記の「$unicode_many」をループで回してやればOK
▼ループ内で一個ずつ文字に戻す
foreach ($unicode_many as $row_unicode) { echo mb_convert_encoding(hex2bin(str_repeat('0', 8 - strlen($row_unicode)).$row_unicode), 'UTF-8', 'UTF-32BE'); }
DBに保存
上記の「$unicode_many」をjsonにして保存すればOK
ただunicodeにしているので文字数的に…カラムの型を気にしなくちゃいけないかもしれない
関数化
// unicodeを文字(1文字)へ変換 function convert_toChar($unicode) { return mb_convert_encoding(hex2bin(str_repeat('0', 8 - strlen($unicode)).$unicode), 'UTF-8', 'UTF-32BE'); } // unicodeを格納した配列を文字列へ変換 function convert_toString($unicode_many) { $string = ''; foreach ($unicode_many as $row_unicode) { $string .= convert_toChar($row_unicode); } return $string; } // 文字(1文字)をunicodeへ変換 function convert_toUnicode($char) { return base_convert(bin2hex(mb_convert_encoding($char, 'UTF-32BE', 'UTF-8')), 16, 16); } // 文字列をunicodeへ変換 function convertString_toUnicode($string) { $length = mb_strlen($string); $ret = []; $s = mb_convert_encoding($string, 'UTF-32BE', 'UTF-8'); for ($i = 0; $i < $length; ++$i) { $tmp_unicode = mb_substr($s, $i, 1, 'UTF-32BE'); $ret[$i] = base_convert(bin2hex($tmp_unicode), 16, 16); } return $ret; }
絵文字について
「utf8mb4」にすれば絵文字は基本、文字化けしないけど、特定の絵文字は文字化けする
さらにブラウザによって表示される・されない…ってのもある
▼一部だけ
- 「🥹 涙をこらえている顔」の絵文字はFirefoxだと表示されるが、Chrome、Edgeは文字化け
- 「😘 投げキッス」がFirefox、Chrome、Edgeで表示されるけど、utf8mb4にしたカラムに保存すると文字化け