CodeIgniter Shift-JISでPOSTされた値をUTF-8で受け取る

Shift-JISでPOSTされた値をUTF-8で受け取る

CodeIgniter内は、UTF-8
HTMLページは、Shift-JIS
という環境で、「accept-charset="utf-8"」を使わずにShift-JISでPOSTされた値をUTF-8で受け取る方法。


POSTが文字化け (Codeigniter-users) - CodeIgniter日本語化 - SourceForge.JP
によると、POSTされた値を
CI_Input内、CI_Utf8のclean_stringが呼ばれる前にUTF-8に変換しておく必要があるとのことなので、
CodeIgniterのフックを使って実装した。

フックの有効化

application/config/config.php

$config['enable_hooks'] = TRUE;//フック機能を有効に設定。
フックの定義

フックは application/config/hooks.php でファイルで定義する。

$hook['pre_system'] = array(
                                'class'    => '',
                                'function' => 'convert_encoding',
                                'filename' => 'Convert_encoding.php',
                                'filepath' => 'hooks',
                                );

これで、pre_system(システムの実行の最初)にapplication/hooks/Convert_encoding.phpのconvert_encodingメソッドが実行される。

文字コード変換を実装

application/hooks/Convert_encoding.php

<?php
function convert_encoding() {
        if(isset($_POST)){
            $_POST = _mbConvertEncodingEx($_POST, "UTF-8", "sjis-win");
        }
}

/**
 * mb_convert_encoding()の拡張
 *
 * @param  mixed  $target       arrayかstring
 * @param  string $toEncoding   エンコード先
 * @param  string $fromEncoding エンコード元(default:null)
 * @return mixed  arrayが来たらarrayを、stringが来たらstringを
 */
function _mbConvertEncodingEx($target, $toEncoding, $fromEncoding = null){
    if (is_array($target)) {
        foreach ($target as $key => $val) {
            if (is_null($fromEncoding)) {
                $fromEncoding = mb_detect_encoding($val);
            }
            $target[$key] = _mbConvertEncodingEx($val, $toEncoding, $fromEncoding);
        }
    }
    else {
        if  (is_null($fromEncoding)) {
            $fromEncoding = mb_detect_encoding($target);
        }
        $target = mb_convert_encoding($target, $toEncoding, $fromEncoding);
    }
    return $target;
}
?>

$_POSTされたデータに配列も含まれる場合があるため、
配列をmb_convert_encodingするプログラム - せとっちの備忘録(技術系)
を利用させていただきました。