作成日: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にしたカラムに保存すると文字化け