CakePHP その20 〜1.2RC2でPC&携帯対応サイトを考えた 〜 [CakePHP]
CakePHP1.2RC2を使って、PC&携帯サイトを作ってみた。
いろんなサイトを参考にしたので、感謝を込めて。珍しく長いです。
前提として、
・個人情報などは一切保有しない。
・携帯は3G以降のみ。
というゆるいサイト向けに使ったので、そのつもりでおねがいします。
追記:コメント欄のあゆ様のコメントも参考にして下さい。
追記2:おれ最前線ねっと様の「CakePHP1.2でprefixルーティング設定時の注意点。[携帯]」もご参考に
まず、認証は標準のAuthコンポーネントを使用する。
下記サイトをほぼまるパクり
ねねとまつの小部屋様「AuthComponentについてのまとめ」
http://blog.ne2ma2.com/archives/160
PC用のは上記で全部済むので、次に携帯(DOCOMO)でもAuthが使えるようにするには session.use_trans_sid を 1 にすればオッケー。
携帯で条件分岐しているところで、ini_set('session.use_trans_sid', 1); を追記。
…設定できない。
そう、くどいようだが、自分が使っているサーバはPHPが未だに4を使用しているので、.htaccess以上じゃなきゃ、session.use_trans_sid の変更ができない。
がびーん。
とおもってたが、下記サイトを参考に(ごっちゃに)して作成
CakePHPフォーラム「Docomoとセッション」
http://cakephp.jp/modules/newbb/viewtopic.php?post_id=1398&topic_id=751&forum=3
d.hetima様「CakePHP に use_trans_sid 風の処理を組み込む」
http://d.hatena.ne.jp/hetima/20070201/1170313526
ただ、上記だとPCへの振り分けが考慮されてないので、Contoroller で AppControllerを継承する時にベースとなるモデルを別々に作って、ワンクッションかまし継承することでできた。
できた!…と思う。
でもコレだと、携帯本体の◀ボタンで画面遷移した時に、セッションが切れてしまう。
そんな時は、携帯の端末IDで持ち回ればオッケー。
rakutoネット様「phpのセッション情報について」
http://study.rakuto.net/exec/bbs/browse/176/
携帯の端末IDについては下記がとても参考になる。
ke-tai.org様「ケータイの端末ID・ユーザIDの取得についてまとめてみました」
http://ke-tai.org/blog/2008/09/08/phoneid/
あれ?これでも◀ボタンで画面遷移するとセッション切れる?
そんな時は、core.php の Security.level を変更。midium でいけると思う。
Configure::write('Security.level', 'midium');
なんか、ただのリンク集になってしまったけど、一応こんな感じでできました。
まだ、実機でちゃんと検証してないけど!
でも、検証後だときっと面倒になって書かなくなっちゃうから、この時点で書いておく。
…ダメだったら追記していきます。変だったら教えてください。
コードはこんな感じ。
追記:肝心のとこ書き忘れてた。
いろんなサイトを参考にしたので、感謝を込めて。珍しく長いです。
前提として、
・個人情報などは一切保有しない。
・携帯は3G以降のみ。
というゆるいサイト向けに使ったので、そのつもりでおねがいします。
追記:コメント欄のあゆ様のコメントも参考にして下さい。
追記2:おれ最前線ねっと様の「CakePHP1.2でprefixルーティング設定時の注意点。[携帯]」もご参考に
まず、認証は標準のAuthコンポーネントを使用する。
下記サイトをほぼまるパクり
ねねとまつの小部屋様「AuthComponentについてのまとめ」
http://blog.ne2ma2.com/archives/160
PC用のは上記で全部済むので、次に携帯(DOCOMO)でもAuthが使えるようにするには session.use_trans_sid を 1 にすればオッケー。
携帯で条件分岐しているところで、ini_set('session.use_trans_sid', 1); を追記。
…設定できない。
そう、くどいようだが、自分が使っているサーバはPHPが未だに4を使用しているので、.htaccess以上じゃなきゃ、session.use_trans_sid の変更ができない。
がびーん。
とおもってたが、下記サイトを参考に(ごっちゃに)して作成
CakePHPフォーラム「Docomoとセッション」
http://cakephp.jp/modules/newbb/viewtopic.php?post_id=1398&topic_id=751&forum=3
d.hetima様「CakePHP に use_trans_sid 風の処理を組み込む」
http://d.hatena.ne.jp/hetima/20070201/1170313526
ただ、上記だとPCへの振り分けが考慮されてないので、Contoroller で AppControllerを継承する時にベースとなるモデルを別々に作って、ワンクッションかまし継承することでできた。
できた!…と思う。
でもコレだと、携帯本体の◀ボタンで画面遷移した時に、セッションが切れてしまう。
そんな時は、携帯の端末IDで持ち回ればオッケー。
rakutoネット様「phpのセッション情報について」
http://study.rakuto.net/exec/bbs/browse/176/
携帯の端末IDについては下記がとても参考になる。
ke-tai.org様「ケータイの端末ID・ユーザIDの取得についてまとめてみました」
http://ke-tai.org/blog/2008/09/08/phoneid/
あれ?これでも◀ボタンで画面遷移するとセッション切れる?
そんな時は、core.php の Security.level を変更。midium でいけると思う。
Configure::write('Security.level', 'midium');
なんか、ただのリンク集になってしまったけど、一応こんな感じでできました。
まだ、実機でちゃんと検証してないけど!
でも、検証後だときっと面倒になって書かなくなっちゃうから、この時点で書いておく。
…ダメだったら追記していきます。変だったら教えてください。
コードはこんな感じ。
追記:肝心のとこ書き忘れてた。
-
まず、core.php のセキュリティ・レベルをmidiumに
config/core.php
//105行目あたり
Configure::write('Session.save', 'usersession');
//150行目あたり
Configure::write('Security.level', 'midium');
-
config/usersession.php を新規作成(d.hetima様のコードをマルコピ)
<?php
if (!isset($_SESSION)) {
if (function_exists('ini_set')) {
ini_set('session.use_trans_sid', 0);
ini_set('url_rewriter.tags', '');
ini_set('session.serialize_handler', 'php');
//クッキーの設定
if(Configure::read('mobile')){
ini_set('session.use_cookies', 0);
}else{
ini_set('session.use_cookies', 1);
}
ini_set('session.cookie_lifetime', $this->cookieLifeTime);
ini_set('session.cookie_path', $this->path);
ini_set('session.gc_probability', 1);
ini_set('session.auto_start', 0);
ini_set('session.save_path', TMP . 'sessions'); //cake
}
}
?> -
bootstrap.php で携帯かどうかを判断
config/bootstrap.php
if(ereg("^/m/",$_SERVER['REQUEST_URI'])){
Configure::write('mobile', 1);
} -
AppControllerに携帯用のを追記
app_contoroller.php
<?php
//まずはPC用の設定
class AppController extends Controller {
function beforeFilter() {
$this->Auth->loginAction = '/models/login';
$this->Auth->logoutAction = '/models/logout';
$this->Auth->loginError = 'ログインエラーです';
$this->Auth->authError = '権限がありません';
$this->Auth->logoutRedirect = '/';
$this->Auth->userModel = 'Model';
}
}
//携帯用の設定(リダイレクトも書き換え)
class MobileAppController extends AppController {
var $layout = "mobile";
var $_needs_session_renew=false; //for Session Fixation
function __construct() {
//ここで携帯IDを取得
if(isset($_SERVER['HTTP_X_DCMGUID'])){
$sid = md5($_SERVER['HTTP_X_DCMGUID']);
}else if(isset($_SERVER['HTTP_X_UP_SUBNO'])){
$sid = md5($_SERVER['HTTP_X_UP_SUBNO']);
}else if(isset($_SERVER['HTTP_X_JPHONE_UID'])){
$sid = md5($_SERVER['HTTP_X_JPHONE_UID']);
}else{
$sid = null;
}
if( preg_match('/^[0-9a-z]{32}$/', $sid) ){
session_id($sid);
$this->_needs_session_renew = true; //for Session Fixation
}
parent::__construct();
}
function beforeFilter(){
//for Session Fixation
if($this->_needs_session_renew){
$this->Session->renew();
}
//PC用Authの設定を上書き
$this->Auth->loginAction = '/m/models/login';
$this->Auth->logoutAction = '/m/models/logout';
$this->Auth->loginError = 'ログインエラーです';
$this->Auth->authError = '権限がありません';
$this->Auth->userModel = 'Model';
}
//携帯用リダイレクト(普通のを使いたかったら AppController::redirect() を使えばいいや)
function redirect($url, $status = null){
$url = $url."?".session_name()."=".session_id(); //転送先URLにセッションIDを自動付加
parent::redirect($url,$status);
}
}
?> -
携帯で使用する各コントローラーは最初に継承するAppControllerをワンクッションさせる ModelsBranchControllerを最初に設定(Qdmail風)。
こうすれば、ヘルパーなどをPCと携帯で振り分けられるメリットもあり。
ただ、可読性を考えて、メソッドは実際のコントローラーにまとめた。
controller/models_controller.php
<?php
//AppControllerを携帯とPCで振り分け
if(Configure::read('mobile')){
//携帯用の設定
class ModelsBranchController extends MobileAppController {
//MobileとかEmojiとか使用したい場合
var $helpers = array('Mobile', 'Emoji');
var $components = array('Auth', 'EmojiData');
}
}else{
//PC用の設定
class ModelsBranchController extends AppController {
var $components = array('Auth');
}
}
//実際のクラス
class ModelsController extends ModelsBranchController {
var $name = 'Models';
function beforeFilter() {
parent::beforeFilter();
//会員ページの除外
$this->Auth->allow('login', 'mobile_login');
}
//PC用
function index(){}
function login(){}
function logout(){
$this->Session->setFlash('ログアウトしました。');
$this->Auth->logout();
$this->redirect('/');
}
//携帯用
function mobile_index(){}
function mobile_login(){}
function mobile_logout(){
$this->Session->setFlash('ログアウトしました。');
$this->Auth->logout();
AppController::redirect('/');
}
}
?> -
viewでのリンクは、下記のようにしたけど、ヘルパー作った方が良いか?
<?php
$sid = '?'.session_name().'='.session_id();
?>
<?=$html->link('ヘルプ', array('controller' => 'pages', 'action' => 'mobile_help'.$sid), array('escape' => false))?>
こんな感じで、今のところうまくいきそうな気配。







参考にさせてもらいます。
携帯サイト。これがまた問題アリアリでメンドクサーなんすよ(笑)
by まさ (2008-09-12 03:44)
niceありがと
携帯サイト、大変だよねぇ。
最近は随分情報が増えてきたけど、あいかわらずキャリア毎の仕様の違いがうざすぎるよ。
この記事は、ほとんどフレームワーク依存だけど、参考にしてもらえれば嬉しい。
by sandman (2008-09-12 17:17)
とても参考にさせてもらってます!
一つバグがあったので報告させてもらいます。
bootstrap.php で下記を書くと
if(ereg("^/m/",$_SERVER['REQUEST_URI'])){
Configure::write('mobile', 1);
}
shellを使う時に怒られてしまいました…。
なのでコントローラー側でどのブランチクラスを使うか分けるようにしました。
一応これで動いていますが、コントローラー内で$_SERVER使うのは微妙ですよね(汗)
//AppControllerを携帯とPCで振り分け
if(ereg("^/m/",$_SERVER['REQUEST_URI'])){
//携帯用の設定
class UsersBranchController extends MobileAppController {
var $components = array('Auth', 'Mobile');
}
}else{
//PC用の設定
class UsersBranchController extends AppController {
var $components = array('Auth', 'Mobile');
}
}
by あゆ (2008-11-23 03:24)
> あゆさん
バグ報告ありがとうございます!& 参考になったのでしたら嬉しいです。
確かに、shell使うときのことを全く考えてませんでした。
参考にさせて頂きます。
>コントローラー内で$_SERVER使うのは微妙ですよね(汗)
うーん、これは考え方次第なんで難しいとろですが、そのほうが扱い易いのであれば、全然オッケーだと思ってます。
そもそも__constructで携帯の振り分けでばんばん使ってますし(苦笑
by sandman (2008-11-24 14:07)