CakePHPでPC/ケータイ/スマートフォン対応サイトを適当に作ってるメモ

CakePHPでPC/ケータイ/スマートフォン対応サイトを適当に作ってるメモ。

  • ケータイ(docomo/Softbank/AU by KDDI)からのアクセス → SJIS変換・出力。
  • docomoはapplication/xhtml+xml
  • 2Gなケータイは今更なので無視。WAP?なにそれ?おいしいの?
  • Willcomも無視。
  • iPhone/iPodAndroidiPhoneに合わせる(手抜き)。
  • コントローラー内でView(View/Theme/Media)の設定可能。(デフォルト:Theme)

app/controller/components/mobile.php

<?php
// 汚いコードだことorz

class MobileComponent extends Object
{
    var $_ua;
    var $_carry;
    var $_layout;
    var $_sjis;
    var $_contentType;
    var $_charset;
    var $view = 'Theme';
    var $controller;
    
    function initialize(&$controller, $settings = array())
    {
        $this->controller =& $controller;
        $this->_set($settings);
        $this->_detectUserAgent();
        $this->controller->userAgentMobile =& $this->_ua;
        $this->_selectLayout();
        $this->controller->set('content_type', $this->_contentType);
        $this->controller->set('charset', $this->_charset);
    }
    
    // call after Controller::beforFilter
    function startup(&$controller)
    {
        //$this->_selectLayout();
        if ($this->view != 'Media') {
            $this->controller->layout = $this->_layout;
            if ($this->view == 'Theme') {
                $this->controller->view = 'Theme';
                $this->controller->theme = $this->_theme;
            }
        }
        
     }
    
    function shutdown(&$controller)
    {
        if ($this->_sjis && $this->view != 'Media') {
            $output = $this->controller->output;
            $output = mb_convert_kana($output, 'rak', 'UTF-8');
            $output = mb_convert_encoding($output, 'SJIS-win', 'UTF-8');
            $this->controller->output = $output;
            header('Content-Type: ' . $this->_contentType . '; charset=' . $this->_charset);
        }
    }
    
    function _detectUserAgent()
    {
        $this->_ua = Net_UserAgent_Mobile::singleton();
        if (!$this->_ua->isNonMobile()) {
            if ($this->_ua->isDoCoMo()) {
                $this->_carry = 'docomo';
            } elseif ($this->_ua->isSoftBank()) {
                $this->_carry = 'softbank';
            } elseif ($this->_ua->isEZweb()) {
                $this->_carry = 'au';
            } elseif ($this->_ua->isWillcom()) {
                $this->_carry = 'willcom';
            }
        } else {
            if (preg_match('!iPhone|iPod!', $this->_ua->getUserAgent())) {
                $this->_carry = 'iphone';
            } elseif (preg_match('!Android!i', $this->_ua->getUserAgent())) {
                $this->_carry = 'android';
            } else {
                $this->_carry = null;
            }
        }
    }
    
    function _selectLayout()
    {
        $layout = 'default';
        $theme = 'default';
        $sjis = false;
        $contentType = 'text/html';
        $charset = 'UTF-8';
        switch ($this->_carry) {
            case 'docomo':
                $contentType = 'application/xhtml+xml';
            case 'softbank':
            case 'au':
                $layout = 'ketai';
                $theme = 'ketai';
                $sjis = true;
                $charset = 'Shift_JIS';
                break;
            case 'iphone':
            case 'android':
                $layout = 'mobile';
                $theme = 'mobile';
                break;
            default:
        }
        $this->_layout = $layout;
        $this->_theme = $theme;
        $this->_sjis = $sjis;
        $this->_contentType = $contentType;
        $this->_charset = $charset;
    }
}

app/config/bootstrap.php

<?php
// Net_UserAgent_Mobileを使う。
App::import('Vendor', 'pear_ini');
App::import('Vendor', 'Net_UserAgent_Mobile', array('file' => 'Net/UserAgent/Mobile.php'));

app/controller/hoge_controller.php

<?php
class HogeController extends AppController
{
    var $components = array('Mobile');

    function index()
    {}
}

viewsの配置とか。

[app]
  [views]
    [themes]
      [default] ※PC
        [hoge]
          [layouts]
            default.ctp
          [hoge]
            index.ctp
      [ketai] ※ケータイ
        [layouts]
          ketai.ctp
        [hoge]
          index.ctp
      [mobile] ※iPhone/iPod/Android
        [layouts]
          mobile.ctp
        [hoge]
          index.ctp

とりあえず期待通りな動きをしてくれてる。今のところ。
layoutは1枚でゴリゴリ判別させればいいという話も無きにしもあらず。