PHPで電源・WiFi利用可能店舗を検索する

(1/1)
モバイラーズオアシス 電源情報API」は、指定した緯度・経度の近くにある電源利用可能な店舗を検索できるWebAPIサービスだ。地図サービスをクラウド連携することで、住所やランドマークから周辺にある電源利用可能な店舗を探すPHPプログラムを作ってみる。

(2022年3月19日)Leafletでマップ移動時に緯度・経度を拾わない不具合を修正した。
(2021年10月17日)PHP8対応,リファラ・チェック改良

目次

サンプル・プログラム:実行例

PHPで電源・WiFi利用可能店舗を検索する
Googleマップ表示
「住所」に、住所やランドマーク、緯度経度を入力して「検索」ボタンをクリックすると、近くにある図書館がGoogleマップ上に表示されるとともに、一覧表示される。

サンプル・プログラム

圧縮ファイルの内容
searchOutlet.phpサンプル・プログラム本体
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。

サンプル・プログラムの流れ

PHPで電源・WiFi利用可能店舗を検索する
プログラムの流れは「PHP で最寄り駅を求める」の時と同じで、緯度・経度から施設情報を求める部分を、「モバイラーズオアシス 電源情報API」に差し替えただけである。

準備:pahooGeoCode クラス

  37: class pahooGeoCode {
  38:     var $items;     //検索結果格納用
  39:     var $error;     //エラー・フラグ
  40:     var $errmsg;    //エラー・メッセージ
  41:     var $hits;      //検索ヒット件数
  42:     var $webapi;    //直前に呼び出したWebAPI URL
  43: 
  44:     //Google Cloud Platform APIキー
  45:     //https://cloud.google.com/maps-platform/
  46:     //※Google Maps APIを利用しないのなら登録不要
  47:     var $GOOGLE_API_KEY_1 = '**************************';   //HTTPリファラ用
  48:     var $GOOGLE_API_KEY_2 = '**************************';   //IP制限用
  49: 
  50:     //Yahoo! JAPAN Webサービス アプリケーションID
  51:     //https://e.developer.yahoo.co.jp/register
  52:     //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  53:     var $YAHOO_APPLICATION_ID = '*****************************';

地図サービスを利用するために、クラスファイル "pahooGeoCode.php" を使用する。組み込み関数  require_once  を使って読めるディレクトリに配置する。ディレクトリは、設定ファイル php.ini に記述されているオプション設定 include_path に設定しておく。
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

地図としてGoogleマップを利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、YOLPマップを利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。

準備:地図サービス(WebAPI)の選択

  52: //地図描画サービスの選択
  53: //    0:Google
  54: //    2:地理院地図・OSM
  55: define('MAPSERVICE', 2);
  56: 
  57: //住所検索サービスの選択
  58: //    0:Google
  59: //    1:Yahoo!JAPAN
  60: //   11:HeartRails Geo API
  61: //   12:OSM Nominatim Search API
  62: //   13:国土地理院ジオコーディングAPI
  63: define('GEOSERVICE', 11);
  64: 
  65: //逆ジオコーディングサービスの選択
  66: //    0:Google
  67: //    1:Yahoo!JAPAN
  68: //   11:HeartRails Geo API
  69: //   21:簡易ジオコーディングサービス
  70: define('REVGEOSERVICE', 0);

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。
住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIOSM Nominatim Search API から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。

モバイラーズオアシス 電源情報API

モバイラーズオアシス 電源情報APIは、入力パラメータ(IN)として GET方式を、出力結果(OUT)がJSONで戻るというAPIである。
WebAPIのURL
URL
https://oasis.mogya.com/api/v1/spots.json

入力パラメータ
フィールド名 要否 内  容
n 必須 検索範囲の北端の緯度(世界測地系)
s 必須 検索範囲の南端の緯度(世界測地系)
e 必須 検索範囲の東端の経度(世界測地系)
w 必須 検索範囲の西端の経度(世界測地系)
lat 任意 検索中心の緯度(世界測地系)
lng 任意 検索中心の経度(世界測地系)
応答データ構造(json) result id ユニークID title 店名 address 住所 tel 電話番号 latitude 緯度 longitude 経度 url 店舗公式サイトのURL wireless 無線LAN(配列) categories name カテゴリ名 image イメージアイコンのURL importance カテゴリの重要度 parent_id 親カテゴリID tag 電源、Qi、禁煙喫煙などの情報(配列) other その他情報(HTML) distance latitude,longitudeで指定した緯度経度からのおおよその距離 mo_url モバイラーズオアシスでの情報ページUR status レスポンス

解説:電源情報検索

 185: /**
 186:  * モバイラーズオアシス 電源情報APIのURLを取得する
 187:  * @param   double $n, $w 北西端の緯度・経度(世界測地系)
 188:  * @param   double $s, $e 南東端の緯度・経度(世界測地系)
 189:  * @return  string URL 電源情報APIのURL
 190: */
 191: function getURL_searchOutletV1($n, $w, $s, $e) {
 192:     return "https://oasis.mogya.com/api/v1/spots.json?n={$n}&w={$w}&s={$s}&e={$e}";
 193: }

 195: /**
 196:  * モバイラーズオアシス電源情報APIを利用して指定座標の近くにある店舗を検索
 197:  * @param   double $latitude  緯度(世界測地系)
 198:  * @param   double $longitude 経度(世界測地系)
 199:  * @param   double $distance  範囲(メートル)
 200:  * @param   array  $items     情報を格納する配列
 201:  * @param   object $pgc       pahooGeoCodeクラス
 202:  * @return  array(ヒットした施設数, メッセージ, APIのURL)
 203: */
 204: function searchOutlet($latitude, $longitude, $distance, &$items, $pgc) {
 205:     list($n, $w) = $pgc->getPointDistance($longitude, $latitude, $distance, 0 - $distance);
 206:     list($s, $e) = $pgc->getPointDistance($longitude, $latitude, 0 - $distance, $distance);
 207: 
 208:     $url  = getURL_searchOutletV1($n, $w, $s, $e);
 209:     $json = @file_get_contents($url);
 210: 
 211:     if ($json == FALSE) {
 212:         $message = 'モバイラーズオアシス電源情報APIが停止';
 213:     } else {
 214:         $obj = json_decode($json);
 215:         $flag = FALSE;
 216:         switch ($obj->status) {
 217:             case 'ZERO_RESULTS':
 218:                 $message = '指定範囲に電源がない';
 219:                 break;
 220:             case 'TOO_MUCH_SPOTS':
 221:                 $message = '検索結果が多すぎる.範囲を絞り込んでください';
 222:                 break;
 223:             case 'INVALID_REQUEST':
 224:                 $message = 'モバイラーズオアシス電源情報API呼び出し不正';
 225:                 break;
 226:             default:
 227:                 $message = '';
 228:                 $flag = TRUE;
 229:                 break;
 230:         }
 231:         if ($flag) {
 232:             $message = '指定範囲に電源はない';
 233:             $i = 1;
 234:             foreach ($obj->results as $key=>$val) {
 235:                 $items[$i]['id']        = num2alpha($i);
 236:                 $items[$i]['title']     = htmlspecialchars($val->title, ENT_QUOTES);
 237:                 $items[$i]['address']   = htmlspecialchars($val->address, ENT_QUOTES);
 238:                 $items[$i]['latitude']  = $val->latitude;
 239:                 $items[$i]['longitude'] = $val->longitude;
 240:                 $items[$i]['url'] = isset($val->url? $val->url : '';
 241:                 $items[$i]['mo_url'] = isset($val->mo_url? $val->mo_url : '';
 242:                 //充電情報
 243:                 $items[$i]['charge'] = '';
 244:                 if (isset($val->tags)) {
 245:                     foreach ($val->tags as $key=>$item) {
 246:                         if (isset($item->name&& preg_match('/用途\:充電/iu', $item->name)) {
 247:                             $items[$i]['charge'] = '可能';
 248:                         }
 249:                     }
 250:                 }
 251:                 //電源情報
 252:                 $items[$i]['powersupply'] = '';
 253:                 if (isset($val->tags)) {
 254:                     $key = 0;
 255:                     foreach ($val->tags as $item) {
 256:                         if (isset($item->name&& preg_match('/電源\:/iu', $item->name)) {
 257:                             $str = ($key > 0? ', ' : '';
 258:                             $str .preg_replace('/電源\:/iu', '', $item->name);
 259:                             $items[$i]['powersupply'.$str;
 260:                             $key++;
 261:                         }
 262:                     }
 263:                 }
 264:                 //Wi-Fi情報
 265:                 $items[$i]['wireless'] = '';
 266:                 if (isset($val->wireless)) {
 267:                     $key = 0;
 268:                     foreach ($val->wireless as $item) {
 269:                         if (isset($item->name)) {
 270:                             $str = ($key > 0? ', ' : '';
 271:                             $str .preg_replace('/用途\:/iu', '', $item->name);
 272:                             $items[$i]['wireless'.$str;
 273:                             $key++;
 274:                         }
 275:                     }
 276:                 }
 277:                 $site = ($items[$i]['url'] == ''?  '' : "<a href=\"{$items[$i]['url']}\" target=\"_blank\">⇒公式サイト</a><br />";
 278:                 $charge = ($items[$i]['charge'] == ''?  'なし' : $items[$i]['charge'];
 279:                 $power  = ($items[$i]['powersupply'] == ''? 'なし' : $items[$i]['powersupply'];
 280:                 $wifi   = ($items[$i]['wireless'] == ''? 'なし' : $items[$i]['wireless'];
 281:                 $items[$i]['description'] =<<< EOT
 282: <span class="small"><a href="{$items[$i]['url']}" target="_blank">{$items[$i]['title']}</a><br />{$site}住所:{$items[$i]['address']}<br />充電:{$charge}<br />電源:{$power}<br />WiFi:{$wifi}</span>
 283: EOT;
 284:                 $i++;
 285:                 $message = '';
 286:                 if ($i > 26)    break;      //検索打ち切り
 287:             }
 288:         }
 289:     }
 290:     return array($i - 1, $message, $url);
 291: }

WebAPIを呼び出して結果を受け取るのはユーザー関数 searchOutlet である。結果は配列変数 $items に格納する。

充電情報については、応答データの から、パターンマッチで充電に関するテキストがあれば格納する。
電源情報については、応答データの から、パターンマッチで電源に関するテキストがあれば格納する。
Wi-Fi情報については、応答データの wireless から、パターンマッチでテキストがあれば格納する。

活用例

電源・WiFiが使える店舗・施設を地図・住所で探す」(みんなの知識 ちょっと便利帳)では、このサンプル・プログラムを活用し、検索しやすいページを作成していただいた。ありがとうございます。

参考サイト

(この項おわり)
header