phpMyAdminやAdminerの文字化けが治らない場合の対処方法

とある複数システムが同居するサーバの VPS 移行を過去二回実施してきました。MySQLのデフォルトのデータベースの設定は、既存他システムのプログラム改変が伴うためできません。ちなみに MySQL の文字コードに関するシステム設定は下記の通り。latin1, binary, utf8 が混在する混沌とした設定です。

mysql> SHOW VARIABLES LIKE 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

さて案の定ですが問題が発生しました。VPS 上で走るプログラムは utf8 を前提とした実装なのですが、一方でどういう訳かデータベース内の文字コードは latin1 で格納されていて、文字コード変換周りも、それを想定された実装となってます。

なーのーで、phpMyAdmin などの管理ツールでテーブル内のデータを表示すると問題が発生します。

- スポンサーリンク -

むむむ・・・文字化けしておるではないか。ちなみに phpMyAdmin は好きじゃないので Adminer というツールを普段は使ってますが、こちらも同じく文字化け。

どの文字化けパターンだろう。というわけで前エントリで記載した文字コード誤変換一覧を作って分析しました。なるほど、latin1 と utf8 の変換エラーなのだなってことがわかりました。

img010.png

adminer-3.6.3 を例にとって説明します。まずは、Source codes 版をダウンロードします。

Adminer の配布版は adminer.php というたった1つのファイルとして提供されていますが、ソースコードとしては 170 弱のファイルが存在し、開発者モード、デザイナーモード等々、用途別にコンパイルして1つのファイルに集約して配布します。また複数ファイルのままの状態でも動作します。今回は開発者向けの adminer ディレクトリで見ていくことにします。

\adminer\drivers\mssql.inc.php

下記の通り、SET NAMES もしくは mysql_set_charset により、接続キャラクタセットを utf8 にセットしています。

28行目付近
     if (method_exists($this, 'set_charset')) {
      $this->set_charset("utf8");
     } else {
      $this->query("SET NAMES utf8");
     }

78行目付近
     if (function_exists('mysql_set_charset')) {
      mysql_set_charset("utf8", $this->_link);
     } else {
      $this->query("SET NAMES utf8");
     }

それぞれ次の命令を発行するのと等価です。

SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;

ここで大凡のバグの原因が読めてきました。データベースそのものは utf8 なのですが、実は latin1 で格納されているので、結果を utf8 で受け取るという設定では文字化けしてしまうわけです。

そこで少々乱暴ですが、下記のようにプログラムを改変します。あくまでも手抜きでもコストをかけずに対処することがコンセプトだったので、オススメできない対処方法ですが、5分あれば取り敢えずの問題は回避され、文字化けしなくなります。

28行目付近
     if (method_exists($this, 'set_charset')) {
      $this->set_charset("latin1");
     } else {
      $this->query("SET NAMES latin1");
     }

78行目付近
     if (function_exists('mysql_set_charset')) {
      mysql_set_charset("latin1", $this->_link);
     } else {
      $this->query("SET NAMES latin1");
     }

536行目付近
 function exact_value($val) {
  return q($val) . " COLLATE latin1_bin";
 }

想定通り文字化けはなくなり意図する結果を得られました。ツールの他の日本語の部分が文字化けすることもなく正常にデータベース閲覧ツールとして使える状態になりました。

img011.png

めでたしめでたし。ちなみにデータベース再構築しても良いよって場合は、「phpmyadminの文字化けが治らない:スタッフブログ | 神戸のホームページ制作会社アストロワークス」をみると良いです。

- スポンサーリンク -