IT/AI救済センター

症状別 /

サイトの文字化けが直らない/「???」「縺ゅ>縺輔▽」が消えない

Content-Type と meta charset、MySQL の接続文字セット、ファイル保存時のBOM、CDN設定。文字化けは複数階層のどこか一段で起きるため、闇雲に変換を走らせると元データを破壊します。切り分けの順序と、二次被害を避けるための判断ラインを示します。

🚨 緊急対応が推奨される症状です

緊急相談を送る
文字化けは古典的なトラブルですが、2026年の現場でも普通に発生します。原因は単純なエンコーディング不一致では終わらず、データベース、ファイルの保存形式、サーバの Content-Type、CDN のキャッシュ、絵文字や旧字体の4バイトUTF-8が絡んで複合化します。直し方が単純に見える割に、原因特定にこそ時間がかかります。

最初に切り分けるべきは「どこで化けているか」です。ブラウザの開発者ツールで該当URLを開き、Network タブから Response Headers の Content-Type を確認します。ここが `text/html; charset=UTF-8` ではなく `text/html` だけだと、ブラウザは古い HTML5 のヒューリスティクス判定に頼り、日本語ページを Shift_JIS と誤推定することがあります。Apache なら `.htaccess` か `httpd.conf` に `AddDefaultCharset UTF-8`、nginx なら server もしくは location ブロックに `charset utf-8;` を入れるだけで直る案件は、今でも一定数あります。

次に HTML 側を見ます。`<meta charset="UTF-8">` は head の先頭付近、ファイル先頭から1024バイト以内に置かれている必要があります。WordPress テーマでヘッダに大量の preconnect や Google Tag Manager、Cookie Banner のスニペットを差し込んだ結果、meta charset 宣言が1024バイトの外に押し出されて文字化けが再発した事故が実際に起きています。プラグインを一個追加しただけで再現する厄介な現象です。

データベース側はもっと深刻です。MySQL の charset は接続単位・テーブル単位・カラム単位の三層に加え、サーバ全体のデフォルトもあり、どれか一段でも不一致だと書き込み時に「?」へ変換されます。一度「?」になったデータは復元不能です。原因調査の前に `SHOW VARIABLES LIKE 'character_set_%';` で接続文字セットを確認し、`SHOW CREATE TABLE` で各テーブルの DEFAULT CHARSET を確認します。Laravel なら `config/database.php` の `charset` と `collation` を `utf8mb4` と `utf8mb4_unicode_ci` に揃えるのが基本ですが、いまだに `utf8` のままのプロジェクトを引き取ることがあります。

ここで重要な落とし穴があります。MySQL の `utf8` は実は `utf8mb3` という3バイトUTF-8 の別名で、絵文字や一部の漢字、たとえば「𠮷野家」の「𠮷」のような U+20000 以降のサロゲートペアが保存できません。問い合わせフォームに絵文字を入れた瞬間に INSERT が失敗するか、「???」に置換されます。utf8mb4 への変換は ALTER TABLE で可能ですが、大規模テーブルではロックとサイズ増加を伴うため、深夜メンテで pt-online-schema-change を使う前提が要ります。

第二の確認点は「ファイルの保存エンコーディング」です。Windows のメモ帳で保存した PHP ファイルは BOM 付きUTF-8 になり、出力直前に `header()` を呼ぼうとして "headers already sent" が起き、結果的に画面崩れや文字化けを誘発します。VS Code のステータスバー右下に `UTF-8 with BOM` と表示されているファイルは要注意で、BOM なし UTF-8 に変換して保存し直します。共同編集現場では Git の `.gitattributes` で `*.php text eol=lf` を強制し、エディタ設定を共有しておかないと、毎週同じ文字化けを別の人が踏みます。

CSV のアップロード機能では Excel で開かれる前提を意識すべきです。Excel for Windows は CSV を CP932(Shift_JIS)として読み込む挙動が初期設定で、UTF-8 のまま吐き出すと「縺ゅ>縺輔▽縺・」のような特徴的な文字列に化けます。BOM 付き UTF-8 で吐き出すのが現実解で、業務 CSV ではこれが事実上の正解です。BOM なしにこだわると、現場の人が毎日30分の手作業を続けます。

旧サイトからの移行時にも頻発します。EUC-JP のテキストを UTF-8 サイトに取り込み、`iconv -f EUC-JP -t UTF-8` を二度走らせた結果、二重エンコードが起きて「テ・コ」のような階段状の崩壊が発生します。復元には元バイト列の特定が必要で、人手では実質不可能です。複数回の自動変換は禁止、バックアップ後に変換は1回だけ、結果を diff で確認、が鉄則です。

CDN も見落とされがちです。Cloudflare の Auto Minify HTML を有効にすると、稀に meta charset の宣言位置が動き、一部ブラウザで文字化けが起きます。Auto Minify は近年のベストプラクティスでは推奨されておらず、ビルド時に minify する構成へ移すのが筋です。

文字化けは「直し方」が単純な割に、原因の特定にこそ時間がかかります。1時間試して直らない、あるいは原因が DB の保存値そのものに見える段階で、それ以上は二次被害(誤った変換で元データを破壊する事故)のリスクが上回ります。早めにバックアップを固定し、切り分けの専門家を入れる判断が、結果的に最も安く済みます。

初動チェックリスト

  1. 1.ブラウザ開発者ツール → Network → Response Headers で Content-Type に charset=UTF-8 が含まれるか確認する
  2. 2.HTML の <meta charset="UTF-8"> が head の先頭から1024バイト以内に置かれているか確認する
  3. 3.MySQL に接続して SHOW VARIABLES LIKE 'character_set_%'; を実行し、接続文字セットを確認する
  4. 4.SHOW CREATE TABLE で各テーブルの DEFAULT CHARSET と COLLATE が utf8mb4 で揃っているか確認する
  5. 5.Laravel なら config/database.php の charset と collation が utf8mb4 / utf8mb4_unicode_ci になっているか確認する
  6. 6.PHP テンプレートが BOM 付き UTF-8 で保存されていないか(VS Code のステータスバー右下)を確認する
  7. 7.Cloudflare の Auto Minify HTML が ON になっていないか確認する(OFF が推奨)
  8. 8.復旧作業の前に必ず該当 DB と該当ディレクトリのバックアップを取得する。変換は1回ずつ実行し、結果を必ず diff で確認する

この症状でお困りなら、まず無料相談

60分無料相談を予約
緊急 AI診断 60分予約