So-net無料ブログ作成
検索選択
Lancers.jp

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');

なんか、ただのリンク集になってしまったけど、一応こんな感じでできました。
まだ、実機でちゃんと検証してないけど!
でも、検証後だときっと面倒になって書かなくなっちゃうから、この時点で書いておく。
…ダメだったら追記していきます。変だったら教えてください。

コードはこんな感じ。
追記:肝心のとこ書き忘れてた。

  1. まず、core.php のセキュリティ・レベルをmidiumに config/core.php //105行目あたり
    Configure::write('Session.save', 'usersession');
    //150行目あたり
    Configure::write('Security.level', 'midium');
  2. 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
        
    }
    }
    ?>
  3. bootstrap.php で携帯かどうかを判断 config/bootstrap.php if(ereg("^/m/",$_SERVER['REQUEST_URI'])){
        
    Configure::write('mobile', 1);
    }
  4. 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);  
        }
    }
    ?>
  5. 携帯で使用する各コントローラーは最初に継承する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('/');
        }
    }
    ?>
  6. viewでのリンクは、下記のようにしたけど、ヘルパー作った方が良いか? <?php
    $sid
    = '?'.session_name().'='.session_id();
    ?>
    <?=$html
    ->link('ヘルプ', array('controller' => 'pages', 'action' => 'mobile_help'.$sid), array('escape' => false))?>
  7. こんな感じで、今のところうまくいきそうな気配。



nice!(1)  コメント(4)  トラックバック(0) 

nice! 1

コメント 4

まさ

参考にさせてもらいます。
携帯サイト。これがまた問題アリアリでメンドクサーなんすよ(笑)
by まさ (2008-09-12 03:44) 

sandman

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) 

sandman

> あゆさん
バグ報告ありがとうございます!& 参考になったのでしたら嬉しいです。

確かに、shell使うときのことを全く考えてませんでした。
参考にさせて頂きます。

>コントローラー内で$_SERVER使うのは微妙ですよね(汗)

うーん、これは考え方次第なんで難しいとろですが、そのほうが扱い易いのであれば、全然オッケーだと思ってます。
そもそも__constructで携帯の振り分けでばんばん使ってますし(苦笑
by sandman (2008-11-24 14:07) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。