今やWebサイトを開設したらモバイルへの対応は必須という状況になってきています。
CakePHPで作ったサイトでも簡単なステップを踏めばPC用とモバイル用を分けて表示するということができたりします。
※ ここで書いたモバイルというのはスマートフォンが中心なので、正確に言えば「CakePHPのサイトをスマートフォンに対応させる」かもしれません。
今回の環境では、CakePHP2.3.7を使っています。
isMobileを使ってモバイル判定をする
CakePHPのRequestHandlerComponentの中には、モバイル判定をしてくれるメソッドが標準で用意されています。
それが、isMobileメソッド でユーザーエージェント内に特定の文字列があるかどうかで判定を行っています。
日本のものでは何故かDocomoだけが入っていますが、ほぼ海外の端末判定しかしてくれません。
まぁ、スマートフォンであれば多くはiPhoneかAndroidになるかと思いますので大部分はカバーできるかもしれませんが。
使い方は単純で、メソッドを呼び出せばアクセス元のユーザーエージェントから自動的に判別してくれます。
ですので、共通の事前処理としてbeforeFilter()などでisMobileを呼び出して判定してあげます。
public function beforeFilter() {
if ($this->request->isMobile()) {
$this->mobile = TRUE;
}
}
次に、モバイルの場合はPC用のテンプレートが使えないので、モバイル専用のテンプレートを用意してあげます。
これは、各アクションの中で
$this->render('mobiePage');
などとしてもいいのですが、PC用のテンプレートと混在すると保守しづらかったり、アクションごとに判定と設定をしていくのは手間なので、beforeRender()でモバイル判定された場合のテンプレートのディレクトリを別で参照するようにしておきます。
function beforeRender() {
if ($this->mobile === TRUE) {
$this->viewPath = 'Mobile';
}
}
これで、モバイル判定された場合はView/Mobileディレクトリが参照されます。
あとは、モバイル用のViewファイルを用意しておきます。
<?php $this->layout = "mobile"; ?>
<div data-role="page">
<div data-role="header" data-theme="b">
<h1>モバイルページ</h1>
</div>
<div role="main" class="ui-content">
<p>モバイルからのアクセスです</p>
</div>
</div>
</body>
</html>
モバイル用のレイアウトファイルも別に用意しておいた方が便利かもしれません。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title><?php echo $title; ?></title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js">
</script>
<script src="/apps/js/jquery.mobile.nestedlists.js">
</script>
</head>
<body>
<?php echo $this->fetch('content'); ?>
これは、jQueryモバイルを使ったレイアウトおよびテンプレートファイルとなりますが、モバイルページの作り方は様々なので環境に応じて作りこみます。
これで一通りモバイルへの対応が完了です。
isMobileのモバイル判定を拡張する
isMobileの判定はマニュアルページにも書いてあるとおり、あまり多くのモバイルに対応しているわけではありません。
これを、その他のモバイル環境でも判定できるように拡張したい場合もあるでしょう。
その前に、isMobileの判定方法を簡単に書いておきます。
/path/to/cakephp/lib/Cake/Controller/Component/RequestHandlerComponent.php
isMobileはRequestHandlerComponentに定義されていると書きましたが、具体的には上記のパスに存在します。
public function isMobile() {
return $this->request->is('mobile') || $this->accepts('wap');
}
この中で呼び出されているis()メソッドは、Network/CakeRequest.phpの中で定義されていて、is()メソッドは_detectorsという特殊な変数の中身に該当するかどうかをチェックする動きをします。
detectorsの中身はデフォルトで下記のように定義されています。
protected $_detectors = array(
'get' => array('env' => 'REQUEST_METHOD', 'value' => 'GET'),
'post' => array('env' => 'REQUEST_METHOD', 'value' => 'POST'),
'put' => array('env' => 'REQUEST_METHOD', 'value' => 'PUT'),
'delete' => array('env' => 'REQUEST_METHOD', 'value' => 'DELETE'),
'head' => array('env' => 'REQUEST_METHOD', 'value' => 'HEAD'),
'options' => array('env' => 'REQUEST_METHOD', 'value' => 'OPTIONS'),
'ssl' => array('env' => 'HTTPS', 'value' => 1),
'ajax' => array('env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'),
'flash' => array('env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'),
'mobile' => array('env' => 'HTTP_USER_AGENT', 'options' => array(
'Android', 'AvantGo', 'BlackBerry', 'DoCoMo', 'Fennec', 'iPod', 'iPhone', 'iPad',
'J2ME', 'MIDP', 'NetFront', 'Nokia', 'Opera Mini', 'Opera Mobi', 'PalmOS', 'PalmSource',
'portalmmm', 'Plucker', 'ReqwirelessWeb', 'SonyEricsson', 'Symbian', 'UP\\.Browser',
'webOS', 'Windows CE', 'Windows Phone OS', 'Xiino'
)),
'requested' => array('param' => 'requested', 'value' => 1)
);
この配列の中で、mobileキーがモバイル判定するためのユーザーエージェントの一部の文字列が入っています。
モバイル判定を拡張したい場合はこれに追加すればいいわけですが、addDetector()という専用のメソッドが用意されています。
例えば、Kindleからのアクセスをモバイル判定にしたい場合、下記のように事前にaddDetector()でKindleという検知用の文字列を追加しておきます。
$this->request->addDetector('mobile', array('options' => array('Kindle')));
if ($this->request->isMobile()) {
$this->mobile = TRUE;
}
これで、isMobile()の判定データを拡張しておけば定義されていない環境からのアクセスでもモバイル判定できるようになります。
[PR]
[PR]