[phpmyadmin] エクスポートするときの「エンコーディングへの変換」が無視されているのを直すの巻

スポンサーリンク

phpmyadmin_export

phpMyAdminを用いてデータベース上のレコードをエクスポートする際、レコードに日本語が含まれると文字化けして正しくエクスポートできない!というのを経験された方は多いのではないでしょうか。

多くの方は、phpMyAdminからエクスポートしてファイルとして保存した後に、保存したファイルをテキストエディタ等で開き、文字コードをSJISやその他希望する文字コードに変換してさらに保存することで、参照可能にされていると思います。

私もその一人でした。UTF-8のレコードをSJIS指定でエクスポートしても、UTF-8のまま出力されてしまうのです。SQL実行画面では正しく日本語が見えるのに、なぜかエクスポートして保存したファイルは文字化けしているんですよね。

今回、最近PHPに関する知識と興味が増えているので、なぜユーザーが指定する文字コードで変換されないのかを調べてみることにしました。長くなるといけないので、今回はシンプルに原因と修正方法をできるだけわかりやすく記述したいと思います。

原因

エクスポート時に選択できる「エンコーディングへの変換」で選択した項目が正しく処理対象として認識されていないから

2014.02.03追記
本記事の下部にありますとおり、バグ報告した結果4.1.7からは修正されるようになりました!
bug #4263 Japanese character encoding not working properly when exportin… · ceecaa4 · phpmyadmin/phpmyadmin · GitHub

修正方法

これでなおります!

phpMyAdminに含まれる「export.php」に1行追加します。

変更前:

  35     /**
  36      * Sets globals from $_POST
  37      *
  38      * - Please keep the parameters in order of their appearance in the form
  39      * - Some of these parameters are not used, as the code below directly
  40      *   verifies from the superglobal $_POST or $_REQUEST
  41      */
  42     $post_params = array(
  43             'db',
  44             'table',
  45             'single_table',

変更後:

  35     /**
  36      * Sets globals from $_POST
  37      *
  38      * - Please keep the parameters in order of their appearance in the form
  39      * - Some of these parameters are not used, as the code below directly
  40      *   verifies from the superglobal $_POST or $_REQUEST
  41      */
  42     $post_params = array(
  43             'knjenc',
  44             'db',
  45             'table',
  46             'single_table',

これで修正は完了です。

今一度phpMyAdminからエクスポートをしてみてください(^^)

以下は少し興味がある方へ

knjencってなに?

エクスポートを行う画面のHTMLソースをブラウザから確認するとわかるのですが、ここでの選択項目は「knjenc」というnameでexport.phpに渡されています。

<form method="post" action="export.php" name="dump">
~省略~
<div class="exportoptions" id="kanji_encoding"><h3>エンコーディングへの変換:</h3>
<ul>
<li> <input type="radio" name="knjenc" value="" checked="checked" id="kj-none"><label for="kj-none">なし</label>
<input type="radio" name="knjenc" value="EUC-JP" id="kj-euc"><label for="kj-euc">EUC</label>
<input type="radio" name="knjenc" value="SJIS" id="kj-sjis"><label for="kj-sjis">SJIS</label>
</li>
<li> <input type="checkbox" name="xkana" value="kana" id="kj-kana">
<label for="kj-kana">全角カナへ変換する</label><br>
</li>
</ul></div>

export.phpでPOSTされてきた値を取り出す際に利用されているname一覧が$post_paramsで指定されておりますが、ここにknjencが含まれないのでせっかく搭載されている変換機能が有効にならずに、そのままエクスポートされてしまっているわけです。

以下はわかる人だけ用

配列$post_paramsに含まれるものを使って配列$_POSTに含まれているものに限り配列$GLOBALSに収めています。

 144     foreach ($post_params as $one_post_param) {
 145         if (isset($_POST[$one_post_param])) {
 146             $GLOBALS[$one_post_param] = $_POST[$one_post_param];
 147         }
 148     }

上記で配列$GLOBALSに収められているべきである $GLOBALS[‘knjenc’] を使って文字変換を行っています。

 332     // Kanji encoding convert feature
 333     if ($GLOBALS['output_kanji_conversion']) {
 334         $line = PMA_Kanji_strConv(
 335             $line,
 336             $GLOBALS['knjenc'],
 337             isset($GLOBALS['xkana']) ? $GLOBALS['xkana'] : ''
 338         );
 339     }

ファンクション「PMA_Kanji_strConv」は libraries/kanji-encoding.lib.php に記述があるファンクションです。

 69  * @param string $str  the string to convert
 70  * @param string $enc  the destination encoding code
 71  * @param string $kana set 'kana' convert to JIS-X208-kana
 72  *
 73  * @global  string $kanji_encoding_list the available encoding codes list
 74  *
 75  * @return string   the converted string
 76  */
 77 function PMA_Kanji_strConv($str, $enc, $kana)
 78 {
 79     global $kanji_encoding_list;
 80
 81     if ($enc == '' && $kana == '') {
 82         return $str;
 83     }
 84     $string_encoding = mb_detect_encoding($str, $kanji_encoding_list);
 85
 86     if ($kana == 'kana') {
 87         $dist = mb_convert_kana($str, 'KV', $string_encoding);
 88         $str  = $dist;
 89     }
 90     if ($string_encoding != $enc && $enc != '') {
 91         $dist = mb_convert_encoding($str, $enc, $string_encoding);
 92     } else {
 93         $dist = $str;
 94     }
 95     return $dist;
 96 } // end of the 'PMA_Kanji_strConv' function

 

ということで、phpMyAdminでエクスポートする際に指定する文字コードは「mb_convert_encoding」を用いて文字変換を行うのに必要とされる要素なのですが、選択した文字コードをexport.phpに渡すときに利用しているname「knjenc」がexport.phpに受け取ってもらえていないというのが原因のまとめになります。

export.phpに正しく認識させるためには、配列「$post_params」へ「knjenc」を追加してあげます。

一応phpMyAdminへバグの報告を行っておきましたので、近い将来修正されるかもしれませんが、それまでは手動で変更してがんばりましょう!

スポンサーリンク

#4263 Japanese character encoding not working properly when exporting from phpmyadmin.

phpMyAdmin / Bugs / #4263 (ok 4.1.7) Japanese character encoding not working properly when exporting from phpmyadmin.

コメント

  1. くりくり より:

    nginxでphpmyadminいれてましたけど、色々いじっていたらおかしくなって面倒でけしましたw

  2. trippyboy より:

    くりくりさん

    phpmyadminって、いままでの意識だと「脆弱性がたくさんあるし利用頻度が少ないからいらない」
    でしたけど、自分以外の一般人がDBから情報を引き出すときなどには便利と思っています。
    SQL文だけ教えてあげれば、phpmyadminからログインして実行するってのも簡単ですからね。
    ちなみに、個人用のこのサーバーには無論phpmyadminは入れていません。

  3. くりくり より:

    こんにちは
    >自分以外の一般人がDBから情報を引き出すときなどには便利と思っています。
    会社でwordpressを増やした時、データベースのメンテナンスをサイト管理者にまかせようとしてwordpressのプラグインや
    phpmyadminを導入しようかなと話ししたんですが、お前がやれと一蹴されました(w
    他のwebクリエイターをみてると御自分でやる方が多いのでそういう先入観がありました。

  4. trippyboy より:

    Web開発者側から見れば、クエリーが通ってるかとか、デバッグ用にテーブル作ったりとか出来たら便利なことはたくさんあるんですけどねぇ。
    全部でなくても少しはサーバ側の知識あったほうが、Web開発は進めやすいと思います(^_^.)

  5. より:

    こんなことになってたとは…参考になりました。

タイトルとURLをコピーしました