App.encodingの設定で文字化け発生
CakePHPの1.3の途中からFormHelperやRequestHandlerのコードにcore.phpのConfigure::write(‘App.encoding’, ‘encoding’);
で設定された値を使う箇所が出てきています。
prefixで携帯の表示を処理している場合、設定された文字コードによって文字化けの影響を受けるおそれがあります。
例えば、UTF-8で作成していて、携帯の出力時に全てShift_JISに変換している場合です。
最初はbeforeRender()内で
Configure::write(‘App.encoding’, ‘Shift_JIS’);
ってやればいいんじゃないの??って思ったけど、
やってみると微妙に文字化けが発生orz
grepしてみると、他にはmultibyte.phpの中などに、App.encodingの値を設定している箇所がある。
どこかで影響を受けているのだろうが、ちゃんとは調べていない;;
とりあえず、RequestHandlerとFormの部分だけ対処すれば文字化けはしない。
以下に対処の方法をメモ。
RequestHandlerComponent
症状
debug値 < 2 の場合にstartup()内で、HTTPのヘッダでtext/htmlのcharsetにApp.encodingが設定される。
したがって、App.encodingの値で表示しようとするため文字化けする。
対処
startup()はbeforeRender()の前に呼ばれるので、
beforeRender(){
if($this->Ktai->is_ktai()){
$this->RequestHandler->respondAs('html', array('charset' => 'Shift_JIS'));
}
}
を追記。
FormHelper
症状
FormHelper::create()内で’encoding’オプションにApp.encodingが設定される。
このencodingオプションはaccept-charset属性の値を設定する。
したがって、携帯の機種によっては、accept-charsetに設定された文字コードでフォームの値が送信されてくる可能性がある。
送られてきた値をサーバー側で変換すると文字化けが発生する。
対処
対処は3つほど考えられる。
1.create()のencodingオプションを全てに追加する。
$this->Form->create('Hoge', array('encoding' => 'shift-jis'));
2.強引に置換。
app_controller.phpのafterFilter内に
if($this->Ktai->is_ktai()){
$this->output = str_replace('accept-charset="utf-8"', 'accept-charset="shift-jis"', $this->output);
}
3.FormHelperを継承してKtaiFormHelperを作る。
名前は何でもいいと思うけど、ここではKtaiFormHelperを作る。
さらに、HackPluginを使って、View側のコードをいじらないで済むようにする。
Hack Pluginは@hiromi2424さんが作成された、コンポーネントやヘルパーのエイリアスの設定を行ってくれるとても便利なプラグインです。
Hack Pluginの設置
githubからダウンロードしたものを次のように配置する。
app/plugins/hack
/app/views/helpers/ktai_form.php
class KtaiFormHelper extends FormHelper{
public $helpers = array('Ktai', 'Html');
public $settings = array(
'encoding' => 'shift-jis',
);
function __construct($settings){
$this->settings = am($this->settings, $settings);
}
function create($model = null, $options = array()){
// e.g.携帯の判定を行って値を変更する
if($this->Ktai->is_ktai()){
$options = am($this->settings, $options);
}
return parent::create($model, $options)
}
}
app/controllers/app_controller.php
//e.g.AppControllerにHelperを読み込む場合
class AppController extends Controller{
public $helpers = array('KtaiForm', 'Hack.Alias' => array('Form' => 'KtaiForm'));
}
これで、View内で$this->KtaiForm->create()ってしなくても
$this->Form->create()で呼び出せます。
つまりは既存のView側のコードのヘルパー名を変更しなくて済みます。