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

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

(2025年8月30日).pahooEnv導入
(2025年6月14日)GoogleMaps JavaScript APIの変更に対応した.

目次

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

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

サンプル・プログラム

圧縮ファイルの内容
searchOutlet.phpサンプル・プログラム本体
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
searchOutlet.php 更新履歴
バージョン 更新日 内容
2.7.0 2025/08/30 .pahooEnv導入
2.6.0 2023/07/16 検索キーの最小・最大長の指定
2.5.0 2023/07/16 国土地理院ジオコーディングAPIを追加
2.4 2021/10/17 PHP8対応,リファラ・チェック改良
2.3 2020/03/21 OSM Nominatim Search API追加
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.8.0 2025/08/10 アクセスキーなどを ".pahooEnd" に分離
6.7.1 2025/07/26 jsLine_Gmap() - bug-fix
6.7.0 2025/07/20 drawJSmap,drawGMap -- 引数 $markerLevel 追加
6.6.0 2025/07/19 drawJSmap,drawGMap,drawLeaflet -- マップ中心マーカー表示引数を追加
6.5.0 2025/06/14 GoogleMaps JavaScript APIの変更に対応
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加

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

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

準備:PHP の https対応

クラウド連携や相手先サイトのデータを読み込むのに https通信を使うため、PHPに OpenSSLモジュールが組み込まれている必要がある。関数  phpinfo  を使って、下図のように表示されればOKだ。
OpenSSL - PHP
そうでない場合は、次の手順に従ってOpenSSLを有効化し、PHPを再起動させる必要がある。

Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dll
Linuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順

これで準備は完了だ。

準備:pahooGeoCode クラス

pahooGeoCode.php

  40: class pahooGeoCode {
  41:     public $items;      // 検索結果格納用
  42:     public $error;      // エラー・フラグ
  43:     public $errmsg;     // エラー・メッセージ
  44:     public $hits;       // 検索ヒット件数
  45:     public $webapi// 直前に呼び出したWebAPI URL
  46: 
  47:     // -- 以下のデータは .env ファイルに記述可能
  48:     // Google Cloud Platform APIキー
  49:     // https://cloud.google.com/maps-platform/
  50:     // ※Google Maps APIを利用しないのなら登録不要
  51:     public $GOOGLE_API_KEY_1 = '';      // HTTPリファラ用
  52:     public $GOOGLE_API_KEY_2 = '';      // IP制限用
  53:     public $GOOGLE_MAP_ID    = '';      // GoogleMaps ID
  54: 
  55:     // Yahoo! JAPAN Webサービス アプリケーションID
  56:     // https://e.developer.yahoo.co.jp/register
  57:     // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  58:     public $YAHOO_APPLICATION_ID = '';
  59: 
  60:     // OSM Nominatim Search API利用時に知らせるメールアドレス
  61:     // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
  62:     // ※OSM Nominatim Search APIを利用しないのなら登録不要
  63:     public $NOMINATIM_EMAIL = '';
  64: 
  65:     // IP2Location.io APIキー
  66:     // https://www.ip2location.io/
  67:     // ※IP2Location.ioを利用しないのなら登録不要
  68:     public $IP2LOCATION_API_KEY = '';

GoogleマップやLeafletなどによる地図描画や住所検索を行うためのクラスが pahooGeoCode である。同梱のクラス・ファイル "pahooGeoCode.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooGeoCodeクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

地図や住所検索として Google を利用するのであれば Google Cloud Platform APIキーマップID が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、IP2Location.ioを利用するのであれば「PHPでIPアドレスやホスト名から住所を求める」を、それぞれ参照されたい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

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

searchOutlet.php

  57: // 地図描画サービスの選択
  58: //    0:Google
  59: //    2:地理院地図・OSM
  60: define('MAPSERVICE', 2);
  61: 
  62: // 住所検索サービスの選択
  63: //    0:Google
  64: //    1:Yahoo!JAPAN
  65: //   11:HeartRails Geo API
  66: //   12:OSM Nominatim Search API
  67: //   13:国土地理院ジオコーディングAPI
  68: define('GEOSERVICE', 11);
  69: 
  70: // 逆ジオコーディングサービスの選択
  71: //    0:Google
  72: //    1:Yahoo!JAPAN
  73: //   11:HeartRails Geo API
  74: //   21:簡易ジオコーディングサービス
  75: 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 レスポンス

解説:電源情報検索

searchOutlet.php

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

searchOutlet.php

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

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

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

活用例

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

参考サイト

(この項おわり)
header