work.log

元エンジニアの備忘録的ブログ

WordPressの wp_is_mobile 関数でモバイル判定

投稿:

WordPress の wp_is_mobile 関数で、コンテンツの出し分けをするメモ書きです。

wp_is_mobile は WordPress 3.4 以降で追加されたモバイル向けの関数で、PHP 関数の is_xxx 系みたく条件分岐したい時に使えます。

これを上手く使うと、スマートフォンの時だけ…とか、PC の場合は…というような処理が可能になります。(レスポンシブデザインに打って付けで、個人的には夢の様な関数だと思ってます)

ようやく試す時間が取れたのでその結果を含め、以下のような内容を書いみたいと思います。

  1. wp_is_mobile 関数について
  2. wp_is_mobile 関数の代替関数を自作
  3. wp_is_mobile 関数のテスト
  4. wp_is_mobile 関数の問題とその他の選択肢

wp_is_mobile 関数について

冒頭でも書いた通り、wp_is_mobile 関数はモバイル向けの条件分岐用関数です。

wp_is_mobile 関数がどうやってデバイスを判断しているかというと、HTTP リクエストヘッダに付いてくるユーザーエージェントを見ているようです。

この関数はコアファイルの wp-includes/vars.php で以下のように定義されています。

/**
 * Test if the current browser runs on a mobile device (smart phone, tablet, etc.)
 *
 * @return bool true|false
 */
function wp_is_mobile() {
	static $is_mobile;

	if ( isset($is_mobile) )
		return $is_mobile;

	if ( empty($_SERVER['HTTP_USER_AGENT']) ) {
		$is_mobile = false;
	} elseif ( strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false // many mobile devices (all iPhone, iPad, etc.)
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
		|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false ) {
			$is_mobile = true;
	} else {
		$is_mobile = false;
	}

	return $is_mobile;
}

この関数はこんな感じに利用できます。

if ( wp_is_mobile() ) {

	/* モバイル向けの処理内容 */

} else {

	/* PC 向けの処理内容 */

}

TRUE か FALSE を返すので、使い方も簡単で便利だと思いますが以下の部分は要注意です。

strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false

コメントに many mobile devices (all iPhone, iPad, etc.) と書かれている通り、iPad もモバイル扱いされています。

なので、タブレットはスマートフォン用でなく、PC と同じに表示させたいと思った場合には意図しない動きになると思います。

その場合は、以下で説明する代替関数を使うと良いと思います。

wp_is_mobile関数の代替関数を自作

上記で説明した問題及び、WordPress 3.4 以前でも同様の事をしたいば場合には関数を自作する方法が使えます。

例えば、以下の様なコードを functions.php に追加するとうまく行くと思います。

function is_mobile() {

	$match = 0;

	$ua = array(
		'iPhone', // iPhone
		'iPod', // iPod touch
		'Android.*Mobile', // 1.5+ Android *** Only mobile
		'Windows.*Phone', // *** Windows Phone
		'dream', // Pre 1.5 Android
		'CUPCAKE', // 1.5+ Android
		'BlackBerry', // BlackBerry
		'webOS', // Palm Pre Experimental
		'incognito', // Other iPhone browser
		'webmate' // Other iPhone browser
	);

	$pattern = '/' . implode( '|', $ua ) . '/i';
	$match   = preg_match( $pattern, $_SERVER['HTTP_USER_AGENT'] );

    if ( $match === 1 ) {
		return TRUE;
	} else {
		return FALSE;
	}

}

自分で必要なユーザーエージェントを追加して判断する感じになります。後は追加したいユーザーエージェントがあれば $ua の配列内に追記していきます。

各ユーザーエージェントは以下のページが参考になります。

userAgent(ユーザーエージェント一覧)

これを応用して、is_tablet みたいなタブレット用関数を自作しても良いかもしれません。

wp_is_mobile関数のテスト

次に、wp_is_mobile 関数と、作成した is_mobile 関数をテストします。

今回、以下のテストページを作成してユーザーエージェント偽装による動作確認をしてみました。

モバイル関数のテストページ

中にはこんなショートコードが仕込んであります。

function mobile_check_code() {

	$html  = "<h4>ユーザーエージェント</h4>\n";
	$html .= $_SERVER['HTTP_USER_AGENT'];

	$html .= "<h4>wp_is_mobile関数の判定</h4>\n";

	if ( wp_is_mobile() ) {
		$html .= "<p>モバイルからのアクセスです。</p>\n";
	} else {
		$html .= "<p>PC からのアクセスです。</p>\n";
	}

	$html .= "<h4>wp_is_mobile関数の判定</h4>\n";

	if ( is_mobile() ) {
		$html .= "<p>モバイルからのアクセスです。</p>\n";
	} else {
		$html .= "<p>PC からのアクセスです。</p>\n";
	}

	return $html;

}
add_shortcode( 'mobilechk', 'mobile_check_code' );

[mobilechk] でこのショートコードを利用できます。

ユーザーエージェントの偽装は FireFox Addon のUser Agent Switcherを利用しました。

テスト結果

テスト時のスクリーンショットをいくつか乗せておきます。

PC

wp-mobile-01

iPhone iOS 4.3

wp-mobile-02

Android 4.0.3

wp-mobile-03

iPad iOS 4.2.1

wp-mobile-04

DoCoMo/2.0 SH901iC

wp-mobile-05

ガラケーはオマケでやりましたが上記の関数では判定不足ですね。ガラケーの現状を見る限り新規に対応しても労力に見合わなそうなので個人的には放置の方針です。

ガラケー時代は ip 制限されている所が多くて表示確認に物凄く手間がかかっていましたが、スマホの進出で随分と楽になった気がします。(ip 制限の悪習が取り払われつつあるので本当にいい時代になりました)

簡単ですが以上の結果となりました。

wp_is_mobile関数の問題とその他の選択肢

最後は個人的に思う wp_is_mobile 関数 (自作含む) の最大の問題点について書きます。

率直に言うと「この関数を使う場合、キャッシュ使ってる人は注意だよ!」って事です。

良くも悪くもアクセスされるデバイスによって出力される HTML が変わってくるので、PHP が生成する HTML をキャッシュするタイプのキャッシュ機構は要注意です。

プラグインタイプの「WP Super Cache」とかなら設定があるっぽいですけど、Nginx, mod_cache, mod_pagespeed …etc は対応が面倒そう。(できんの?) 未検証だけど APC は中間コードキャッシュだから大丈夫だよね?とか色々考えものです。

もし心当たりがある場合は、最寄りのインフラ担当にキャッシュ機構の詳細を確認すると良いと思います。下手するとスマホ向けの HTML がキャッシュされてて…って事があると思います。

では、これに影響されない方法はというと今やってるのはこんな感じ。

.sp-view {
	display: none;
}

@media screen and (max-width: 400px) {

	.pc-view {
		display: none;
	}

	.sp-view {
		display: inline;
	}

}

スタイルシートで表示したり、隠したりという具合。

もちろん意図した表示になりますけど、広告だったり外部リンクだったりを javascript で分ける必要がある場合、PC 用とスマートフォン用の 2 つを読み込まなければなりません。

例えばこんな感じに、専用の javascript が用意されている場合とか。

<script src=”http://example.jp/pc.js”></scirpt>
<script src=”http://example.jp/sp.js”></scirpt>

無意味にどちらも読み込むのは、外部リンク先にとってもきっと迷惑ですよね^^;

キャッシュ機構でサーバリソースの消費を抑えたいけど関数特有の問題が出る恐れがある、完全な動的表示にした場合、アクセス過多の時にサーバリソースが不足する…

といった悩ましい部分があるのも事実ですが、このモバイル判定は魅力的です。キャッシュ機構による問題は色々検証してみたいと思います。

以上、簡単ですが WordPress のモバイル判定については以上となります。