MobileProfile
勉強会で気になったので 自分で作ったモバイル端末用判別・詳細情報取得用クラス めっさ仕事で使ってます。
<?php /** * 機種情報取得(おおよその端末データ取得) * @auther のびー */ class MobileProfile{ static $ins= null; // モバイルの情報 var $ua; var $carrier; var $minor; var $width; var $height; var $htmltype; var $uid; //モバイルのプロフィール詳細 var $id; var $device_name; var $name; var $maker; var $series; var $language; var $language_ver; var $browser_size; var $display_size; var $is_decome; var $decome_ver; var $connect_type; var $color; var $is_gif; var $is_jpg; var $is_png; var $camera; var $sub_camera; var $appli; var $appli_ver; var $appli_size; var $arrival_melody; var $is_arrival_music; var $is_arrival_full_music; var $is_arrival_movie; var $movie_type; var $flash; var $is_gps; var $is_ssl; var $mobile_customize; var $device_cash; var $release_date; var $modify_deta; var $mobileData; /** * CONSTRUCTOR */ function MobileProfile() { self::$ins =& $this; self::$ins->setUa($_SERVER['HTTP_USER_AGENT']); self::$ins->carrierSet(); self::$ins->setMobile(); } /** * 静的に呼び出された時に自身でインスタンスを取得する */ function getInstance(){ if (null === self::$ins){ new MobileProfile(); } } /** * METHOD */ function carrierSet() { self::getInstance(); self::$ins->ins->carrier = ""; self::$ins->minor = ""; switch(TRUE){ //DOCOMO端末 case (self::$ins->isDocomo()): self::$ins->setCarrier("DoCoMo"); break; //SOFTBANK端末 case (self::$ins->isSoftbank()): self::$ins->setCarrier("Softbank"); break; //KDDI端末 case (self::$ins->isEzweb()): self::$ins->setCarrier("au"); break; //WILLCOM端末 case (self::$ins->isWillcom()): self::$ins->setCarrier("WILLCOM"); break; //googlebot判定 case (self::$ins->isGooglebot()): self::$ins->setCarrier("GOOGLE"); break; //i-robot判定 case (self::$ins->isIrobot()): self::$ins->setCarrier("I-ROBOT"); break; //検証用PC default: self::$ins->setCarrier('OTHER'); } } /** * 端末の詳細情報をセット */ function setMobile() { self::getInstance(); switch(self::$ins->carrier){ case ('DoCoMo'): preg_match("/^DoCoMo\/[0-9\.]{3}[ \/]([^\/\( ]*)/",self::$ins->ua,$ma); $deviceName = $ma[1]; preg_match("/[\(|\/]c([0-9]{2,3})[\)|;|\/]/",self::$ins->ua."/",$ma); self::$ins->setDeviceCash($ma[1]*1000); //下位端末レベルのFOMAはMOVA扱い $lowar = array("F2051"=>true,"N2051"=>true,"P2102V"=>true, "F2102V"=>true,"N2102V"=>true, "N2701"=>true,"NM850iG"=>true, "N2001"=>true,"N2002"=>true,"P2002"=>true,"D2101V"=>true, "P2101V"=>true,"SH2101V"=>true,"T2101V"=>true); //MOVA(一部FOMA端末を含む) if(preg_match("/^DoCoMo\/1\.0/",self::$ins->ua) || isset($lowar[$deviceName])){ self::$ins->setMinor('MOVA'); if($ma[1] < '20'){ self::$ins->setWidth(120); self::$ins->setHeight(180); }else{ self::$ins->setWidth(200); self::$ins->setHeight(180); } self::$ins->setHtmlType("HTML"); $buf = explode("/",self::$ins->ua); self::$ins->setDeviceName($buf[2]); //FOMA }else{ self::$ins->setMinor('FOMA'); self::$ins->setWidth(240); self::$ins->setHeight(320); self::$ins->setHtmlType("XHTML"); self::$ins->setDeviceName($deviceName); } break; case('au'): //WAP1 if (preg_match("/^UP\.Browser/",self::$ins->ua)) { self::$ins->setMinor('WAP1'); self::$ins->setHtmlType("HTML"); //WAP2 }else{ self::$ins->setMinor('WAP2'); self::$ins->setHtmlType("XHTML"); } if(isset($_SERVER['HTTP_X_UP_DEVCAP_SCREENPIXELS'])){ list($w,$h) = split(',',$_SERVER['HTTP_X_UP_DEVCAP_SCREENPIXELS']); }else{ $w = 96; $h = 96; } self::$ins->setWidth($w); self::$ins->setHeight($h); if(isset($_SERVER['HTTP_X_UP_DEVCAP_MAX_PDU'])){ self::$ins->setDeviceCash($_SERVER['HTTP_X_UP_DEVCAP_MAX_PDU']); }else{ self::$ins->setDeviceCash(200000); } $n = explode("-",self::$ins->ua); $device = explode(" ",$n[1]); self::$ins->setDeviceName($device[0]); break; case('Softbank'): if(preg_match("/^J\-PHONE\/2/",self::$ins->ua) || preg_match("/^J\-PHONE\/3/",self::$ins->ua)){ //C型 self::$ins->setMinor("TYPEC"); self::$ins->setHtmlType("HTML"); self::$ins->setDeviceCash(6000); }elseif(preg_match("/^J\-PHONE\/4/",self::$ins->ua)){ //P型 self::$ins->setMinor("TYPEP"); self::$ins->setHtmlType("HTML"); self::$ins->setDeviceCash(12000); }else if(preg_match("/^J\-PHONE\/5/",self::$ins->ua)){ //W型 self::$ins->setMinor("TYPEW"); self::$ins->setHtmlType("XHTML"); self::$ins->setDeviceCash(200000); }else if(preg_match("/^MOT\-/",self::$ins->ua) || preg_match("/^Vodafone\//",self::$ins->ua) || preg_match("/^SoftBank\//",self::$ins->ua)){ //3GC型 self::$ins->setMinor("3GC"); self::$ins->setHtmlType("XHTML"); self::$ins->setDeviceCash(300000); } if(isset($_SERVER['HTTP_X_JPHONE_DISPLAY'])){ list($w,$h) = split('\*',$_SERVER['HTTP_X_JPHONE_DISPLAY']); }else{ $w = 96; $h = 96; } self::$ins->setWidth($w); self::$ins->setHeight($h); if(isset($_SERVER['HTTP_X_JPHONE_MSNAME'])){ self::$ins->setDeviceName($_SERVER['HTTP_X_JPHONE_MSNAME']); }else{ self::$ins->setDeviceName(""); } break; case('OTHER'): self::$ins->setMinor("PC"); self::$ins->setWidth(240); self::$ins->setHeight(320); self::$ins->setHtmlType("XHTML"); self::$ins->setDeviceCash(99999999); $pc = (isset($_REQUEST['pc']))?$_REQUEST['pc']:""; self::$ins->setDeviceName("PC"); break; } } /** * 端末詳細データ取得(共通管理ファイルより) * @param String device_name 端末ID */ function getMobileDetail($device_name=null) { self::getInstance(); if(!$device_name){ $device_name = self::$ins->device_name; } $dirfile = __FILE__; $dir_name = str_replace(basename(__FILE__),'',$dirfile); $dir_name .= 'MobileProfileData/'; $carrier = self::$ins->carrier; $carrier = strtolower($carrier); //データ配列読み込み if(file_exists($dir_name.$carrier.'Data.php')){ require_once $dir_name.$carrier.'Data.php'; if(!$this->mobileData){ $this->mobileData = $modile_detail; } }else{ return FALSE; } if(isset($this->mobileData[$device_name])){ foreach($this->mobileData[$device_name] as $key => $val){ self::$ins->{$key} = $val; } if(isset(self::$ins->display_size)){ list(self::$ins->height,self::$ins->width) = explode('*',self::$ins->display_size); } return $this->mobileData[$device_name]; //TODO //すでにセットしてあるプロパティの値を上書き }else{ return FALSE; } } /** * 公式UIDの取得 */ function getPublicUid() { self::getInstance(); $uid = ''; switch(self::$ins->carrier){ case('DOCOMO'): //CPの守秘義務に引っかかるかもなので消しときます break; case('EZWEB'): //CPの守秘義務に引っかかるかもなので消しときます break; case('SOFTBANK'): //CPの守秘義務に引っかかるかもなので消しときます break; default : $uid = TESTUID; //定数で適当なUIDを定義 break; } return $uid; } /** * 非公式UTN取得 * */ function getNotPublicUid() { $uid = FALSE; switch(self::$ins->carrier){ case('DOCOMO'): //FOMAの場合はFOMAカード識別番号を使う if(ereg("DoCoMo/2\.0.*;icc(.*)\)$",self::$ins->ua,$regs1) == TRUE){ $uid = $regs1[1]; }elseif(ereg("DoCoMo/1\.0/.*ser(.*)$",self::$ins->ua,$regs2) == TRUE){ //movaの場合は端末製造番号を使う $uid = $regs2[1]; } break; case('EZWEB'): if(isset($_SERVER['HTTP_X_UP_SUBNO'])){ $uid = $_SERVER['HTTP_X_UP_SUBNO']; } break; case('SOFTBANK'): if(isset($_SERVER['HTTP_X_JPHONE_UID'])){ $uid = substr($_SERVER['HTTP_X_JPHONE_UID'],1); }elseif(isset($_SERVER["x-jphone-uid"])){ $uid = $_SERVER["x-jphone-uid"]; } break; default : $uid = 'TESTUID'; break; } return $uid; } /** * キャリア判定(DOCOMO) */ function isDocomo() { if(preg_match("/^DoCoMo/",self::$ins->ua)){ return TRUE; }else{ return FALSE; } } /** * キャリア判定(SOFTBANK) */ function isSoftbank() { if(preg_match("/^J\-PHONE/",self::$ins->ua) || preg_match("/^MOT\-/",self::$ins->ua) || preg_match("/^Vodafone\//",self::$ins->ua) || preg_match("/^SoftBank\//",self::$ins->ua)){ return TRUE; }else{ return FALSE; } } /** * キャリア判定(EZWEB) */ function isEzweb() { if(preg_match("/^UP\.Browser/",self::$ins->ua) || preg_match("/^KDDI/",self::$ins->ua)){ return TRUE; }else{ return FALSE; } } /** * キャリア判定(WILLCOM) */ function isWillcom() { return FALSE; } /** * キャリア判定(GOOGLEBOT) */ function isGooglebot() { return FALSE; } function isIrobot() { return FALSE; } /** * SETTER */ function setDeviceName($arg) { self::$ins->device_name = $arg; } function setHtmlType($arg) { self::$ins->htmltype = $arg; } function setUa($arg) { self::$ins->ua = $arg; } function setUid($arg) { self::$ins->uid = $arg; } function setDeviceCash($arg) { self::$ins->device_cash = $arg; } function setWidth($arg) { self::$ins->width = $arg; } function setHeight($arg) { self::$ins->height = $arg; } function setMinor($arg) { self::$ins->minor = $arg; } function setCarrier($arg) { self::$ins->carrier = $arg; } /** * GETTER */ //自由に取得できるgeter function get($arg) { self::getInstance(); if(!$arg){ return FALSE; } $ret = FALSE; if(is_array($arg)){ foreach($arg as $val){ if(isset(self::$ins->{$val})){ $ret[$val] = self::$ins->{$val}; } } }else{ if(isset(self::$ins->{$arg})){ $ret = self::$ins->{$arg}; }else{ return FALSE; } } return $ret; } } ?>
ってなクラスを使ってます
クラスと同一ディレクトリ内に
『MobileProfileData』
ってディレクトリを作成して
その中に
auData.php ←au用の端末詳細情報配列
docomoData.php ←ドコモ用
otherData.php ←全キャリア用
softbankData.php←ソフトバンク用
って各ファイルを作成
ファイルの中身は
<?php 'HI3C' => array('id' => '661','device_name' => 'HI3C','name' => 'W61H', 'carrier' => 'EZweb','maker' => '日立','series' => 'W6x', 'language' => 'XHTML','language_ver' => '0','browser_size' => 380*240', 'display_size' => '400*240','is_decome' => 'YES','decome_ver' => '2', 'connect_type' => 'CDMA2000 1X EV-DO','color' => '65535','is_gif' => 'YES', 'is_jpg' => 'YES','is_png' => 'YES','camera' => '200','sub_camera' => '0', 'appli' => 'BREW','appli_ver' => '3.1','appli_size' => '0', 'arrival_melody' => '0','is_arrival_music' => 'YES', 'is_arrival_full_music' => 'YES','is_arrival_movie' => 'YES', 'movie_type' => 'amc,3gp,3g2','flash' => 'FL2.0','is_gps' => 'YES', 'is_ssl' => 'YES','mobile_customize' => 'NO', 'device_cash' => '131072', 'release_date' => '9999-12-31 23:59:59', 'modify_deta' => '2008-04-02 11:25:14',) ?>
って配列が大量に並んでます。
ちなみに弊社ではこの配列はDBで保存して端末が発売されるたびに更新かけてます
バッチ組んで各キャリアごとの上記ファイルを生成。
配列が大きすぎるとか思うなら世代ごとにさらに詳細にファイル分割してやればすむかなぁと思ってますよ。
んで、使い方
超簡単
<?php //newしてやって $LIB_MP = new MobileProfile(); //端末名称取得 この時点で大雑把な一般的な数値が取得可能 $device_name = $LIB_MP->get("device_name"); //端末が登録されていなければ if($device_name == 'PC'){ //SH904用のProfileでも入れとけばいいんじゃね? $device_name = 'SH904i'; } //で、詳細情報取得 $LIB_ARR_MP = $LIB_MP->getMobileDetail($device_name); //なんでか取れなかったら if(!$LIB_ARR_MP){ //もっかいSH904を取得してみる $LIB_ARR_MP = $LIB_MP->getMobileDetail("SH904i"); } //とりあえず出力してみる? if($LIB_ARR_MP){ foreach($LIB_ARR_MP as $key => $val){ $str .= sprintf("%20s %s",$key,":".$val)."\n"; } } ?>
上記やってやれば
id :395 device_name :SH904i name :SH904i carrier :DoCoMo maker :SHARP series :FOMA904i language :XHTML language_ver :2.1 browser_size :320*240 display_size :400*240 is_decome :YES decome_ver :3 connect_type :WCDMA color :262144 is_gif :YES is_jpg :YES is_png :NO camera :320 sub_camera :11 appli :Java appli_ver :5 appli_size :1024 arrival_melody :128 is_arrival_music :YES is_arrival_full_music:YES is_arrival_movie :YES movie_type :3gp flash :FL1.1 is_gps :YES is_ssl :YES mobile_customize : device_cash :102400 release_date :2007-05-2500:00:00 modify_deta :0000-00-0000:00:00
ってなデータが取得できるんでないかな?
ちなみに弊社は検証はほぼPCです。
おれおれふれーむわーく(笑)でPCからの検証しやすくやってるんで。
細かい表示周りや最終的なチェックは全部端末でやりますけどね もちろん。
正直ドコモの端末以外は環境変数でほぼ全ての情報が取れますよ。
ドコモのためだけにDBにデータ持ってるようなもんなんで
少なくとも環境変数にブラウザサイズだけでも提供してもらえるとありがたいんですけどね・・・
ってことで上記方法で端末判定行ってます。
DBさえ作ってしまえば端末発売毎の登録の煩わしさだけで済むので
普段の対応考えると管理画面を作っちゃえば割りと楽です。
ってことで次は絵文字変換行って見ますか?
気が向いたら書きます。