CakePHP1.3でPCと携帯の両対応

PCではUTF-8でOKなのですが、モバイルはUTF-8への対応が未だに微妙なので、Shift_JISに変換します。

僕は以下のような条件で作ることが多いです

  • モバイル用のlayoutファイルを用意する
  • prefixでモバイルの処理を切り分け
  • Ktai Libraryは使わない
  • 絵文字を使わない

モバイル用のlayoutファイルを用意する

app/views/layout/mobile.ctp のファイル名で作ります。

その時に、charsetの指定をShift_JISにしておきます。

<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">

prefixでモバイルの処理を切り分け

prefixの指定を追加

app/config/core.php

Configure::write('Routing.prefixes', array('admin', 'mobile'));

mobileを追加しています。

ルーティングの設定

app/config/routes.php

Router::connect('/mobile/:controller/:action', array('mobile' => true));

コントローラーにモバイル用の処理を記述する

function mobile_index() {} // /mobile/{コントローラー}/index
function mobile_view() {} // /mobile/{コントローラー}/view
function mobile_add() {} // /mobile/{コントローラー}/add
function mobile_edit() {} // /mobile/{コントローラー}/edit
function mobile_delete() {} // /mobile/{コントローラー}/delete

Viewファイルの作成

app/views/{コントローラー}/mobile_index.ctp
app/views/{コントローラー}/mobile_view.ctp
app/views/{コントローラー}/mobile_add.ctp
app/views/{コントローラー}/mobile_edit.ctp

layout切り替え処理を追加する

app/app_controller.php

function beforeRender() {
	if(!empty($this->params['prefix']) && $this->params['prefix']=='admin' && !empty($this->params['admin'])) {
		$this->layout='admin';
	} elseif(!empty($this->params['prefix']) && $this->params['prefix']=='mobile' && !empty($this->params['mobile'])) {
		$this->layout='mobile';
	}
}

admin prefixも使っている場合です。

文字コード変換処理

PCはUTF-8で、携帯だけShift_JISに変換します。

app/app_controller.php

function beforeFilter(){
	if(!empty($this->params['prefix']) && $this->params['prefix']=='mobile' && !empty($this->params['mobile'])) {
		if(!empty($this->data)){
			mb_convert_variables('UTF-8', 'SJIS-win', $this->data);
		}
	}
}
function afterFilter() {
	if(!empty($this->params['prefix']) && $this->params['prefix']=='mobile' && !empty($this->params['mobile'])) {
		$this->output = mb_convert_encoding($this->output, 'SJIS-win', 'UTF-8');
	}
}

beforeFilter()の方には、Shift_JISで送信されたデータをUTF-8に変換する処理を追加します。
afterFilter()の方には、UTF-8でレンダリングされた出力内容を、Shift_JISに変換する処理を追加します。

この対応中に1つハマったところがありました…後述してありますので、参照してください。

Ktai Libraryは使わない

Ktai LibraryというCakePHP 1.3までに対応したヘルパー、コンポーネントの総称のようです。
導入すると煩わしい絵文字の変換も上手いことやってくれるみたいですね!

絵文字を使わない

絵文字は変換が手間なこともあって使っていません。
Ktai Libraryを使うとその辺りやってくれるみたいなので、導入すると良いかもしれませんね。

トラブルシューティング

実機だと問題ないのに、PCで見ると文字化けする場合

$this->Form->create()で生成されるformタグについているaccept-charsetが原因で、Shift_JISで送信されるはずのデータがUTF-8で送信されていて、文字化けが発生する問題がありました。
accept-charsetにはUTF-8が設定されています。

<form method="post" action="/{コントローラ}/add" accept-charset="utf-8">

accept-charsetが有効でないブラウザ(例えばIE7)では文字化けが発生しないのですが、ChromeやFirefox、IE9などはaccept-charsetが有効なので文字化けが発生します。
実機だと問題ないのに、FirefoxのFireMobileSimulatorだと文字化けが発生する。なんて場合はこれが原因かもしれません。ハマりました…

解決方法

accept-charsetを出力しないようにするには、createメソッドの第二引数(オプション)に、「’encoding’ => null」を設定するだけです。

こんなかんじ。

<?php echo $this->Form->create('User', array('encoding' => null)); ?>

もしかしたらView側を変えなくても良いかも

1つずつ書くのが面倒なので、app/config/core.phpで設定されている「App.encoding」

Configure::write('App.encoding', 'UTF-8');

をbeforeRenderのレイアウト変更を行なっている部分で、上書きしてしまえば良いんではないかと思ったりもしています。(試していません)
accept-charsetは、createメソッドのencodingのオプションの指定がない場合は、「App.encoding」の値を利用するためです。

参考サイト

コメントは受け付けていません。