PHPで緯度・経度から住所を求める

(1/1)
今回は「PHPで住所・ランドマークから緯度・経度を求める」と逆のプログラム、すなわち、GoogleYahoo!JAPANHeartRails簡易逆ジオコーディングサービスのいずれかの逆ジオコーディングサービスを利用し、入力された緯度・経度から住所を求めるPHPプログラムをつくる。

(2021年9月22日)PHP8対応,リファラ・チェック改良

目次

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

PHPで緯度・経度から住所を求める

サンプル・プログラム

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

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

PHPで緯度・経度から住所を求める

準備: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の登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、それぞれ参照されたい。

準備:逆ジオコーディングサービスの選択

  42: //逆ジオコーディングサービスの選択
  43: //    0:Google
  44: //    1:Yahoo!JAPAN
  45: //   11:HeartRails Geo API
  46: //   21:簡易ジオコーディングサービス
  47: define('REVGEOSERVICE', 11);

逆ジオコーディングサービスとして使うWebAPIは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
住所検索サービスの制約
サービス名 制 約
0 Google 有料(決められた無料枠あり)。
1 Yahoo!JAPAN 無料(?)。郵便番号が取得できない。
11 HeartRails Geo API 無料。市街地ではビル名が戻ることがある。
21 簡易ジオコーディングサービス 無料。郵便番号が取得できない。

「Google Geocoding API」による住所変換

Google Geocoding API」は、入力パラメータ(IN)は GET 渡しで、出力結果(OUT)はXMLなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
WebAPIのURL
URL
https://maps.googleapis.com/maps/api/geocode/xml

入力パラメータ
フィールド名 要否 内  容
key 必須 APIキー
latlng 必須 検索対象の緯度,経度(世界測地系,10進数の度表記)
language 任意 使用言語。ja など
sensor 任意 true または false
応答データ構造(xml) GeocodeResponse status OK result type street_address formatted_address フォーマット済み住所 address_component type political:行政区画 type sublocality_level_*:街区以下 type locality:市区町村名 type administrative_area_*:都道府県名 type country:国名 type postal_code:郵便番号 long_name 長い名前 short_name 短い名前

解説:GoogleMaps API Geocoding

WebAPIを呼び出し、結果を配列変数に代入する処理は、これまでのサンプル・プログラムと同様である。
得られる要素が複数あるが、type=street_address であるものが住所表記であるので、これを選別して配列に格納してゆく。

「Yahoo!リバースジオコーダAPI」による住所変換

Yahoo!リバースジオコーダAPI」は、入力パラメータ(IN)は GET 渡しで、出力結果(OUT)はXMLなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
WebAPIのURL
URL
https://map.yahooapis.jp/geoapi/V1/reverseGeoCoder

入力パラメータ
フィールド名 要否 内  容
appid 必須 アプリケーションID
lat 必須 検索対象の緯度(世界測地系,10進数の度表記)
lng 必須 検索対象の経度(世界測地系,10進数の度表記)
datum 任意 測地系
wgs:世界測地系(デフォルト)
tky:日本測地系
output 任意 出力形式:xml(デフォルト)/json
callback 任意 JSONPとして出力する際のコールバック関数名を入力するためのパラメータ。UTF-8でエンコードした文字列を入力する。
応答データ構造(xml) YDF ResultInfo Count レスポンスに含まれるデータ件数 Total 全データ件数 Start レスポンスの開始位置 Status 200:正常終了 Description データの説明 Copyright 著作権表記 Feature Property Country Code 国コード(ISO) Name 国名 Address 整形済み住所 AddressElement Name 部分住所 Kana よみ(平仮名) Level prefecture:都道府県名 Level city:市区町村名 Level oaza:大字・町村名 Level aza:字 Level detail1:街区以下 Code 行政コード

解説:Yahoo!リバースジオコーダAPI

WebAPIを呼び出し、結果を配列変数に代入する処理は、これまでのサンプル・プログラムと同様である。

「HeartRails Geo API」による住所変換

HeartRails Geo API - 緯度経度による住所検索 API」は、入力パラメータ(IN)は GET 渡しで、出力結果(OUT)はXMLなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
WebAPIのURL
URL
https://geoapi.heartrails.com/api/xml?method=searchByGeoLocation

入力パラメータ
フィールド名 要否 内  容
method 必須 メソッド名:searchByGeolocation(固定)
y 必須 検索対象の緯度(世界測地系,10進数の度表記)
x 必須 検索対象の経度(世界測地系,10進数の度表記)
応答データ構造(xml) response location prefecture 都道府県名 city 市区町村名 city-kana 市区町村名よみ(平仮名) town 町域名 town-kana 町域名よみ(平仮名) postal 郵便番号

解説:HeartRails Geo API

WebAPIを呼び出し、結果を配列変数に代入する処理は、これまでのサンプル・プログラムと同様である。

「簡易逆ジオコーディングサービス」による住所変換

簡易逆ジオコーディングサービス」は、入力パラメータ(IN)は GET 渡しで、出力結果(OUT)は XML で戻るというAPIである。国立研究開発法人農業・食品産業技術総合研究機構 西日本農業研究センター 営農生産体系研究領域の研究成果だ。2020年(令和2年)4月1日、URLが変更された。
今回使う入力パラメータと出力結果のデータ構造を以下に示す。バージョン2の出力を利用する。
なお、入力する緯度・経度は世界測地系(wgs84)であることに留意されたい。

出典: 農研機構 (https://aginfo.cgk.affrc.go.jp/)
WebAPIのURL
URL
https://aginfo.cgk.affrc.go.jp/ws/rgeocode.php

入力パラメータ
フィールド名 要否 内  容
key 任意 出力文書のバージョン。現在は 1 または 2 のみ有効。省略時はバージョン 1。
lat 必須 検索対象点の緯度(世界測地系,10進数の度表記)
lon 必須 検索対象点の経度(世界測地系,10進数の度表記)
jsonp / php / ponp 任意 JSONP, PHPシリアライズ, PONP の各文書種別を指定する。いずれの指定も無い場合はXML文書を応答文書とする。
応答データ構造(xml) rgeocode status 正常終了なら "true", それ以外は "false" error エラー理由 result prefecture pcode 都道府県コード pname 都道府県名 municipality mcode 市町村コード mname 市町村名 local section 町丁目・字など homenumber 番地 argument latitude 緯度 longitude 経度 meta name メタ情報名 content メタ情報

解説:簡易逆ジオコーディングサービス

WebAPIを呼び出し、結果を配列変数に代入する処理は、これまでのサンプル・プログラムと同様である。

解説:検索と結果取得

メソッド getAddress3 は、引数 $api の値によって、Google用メソッド getGoogleAddress、Yahoo!用メソッド getYOLP_Address、HeartRails Geo API用メソッド getHeartRailsGeo_Address、簡易ジオコーディングサービス用メソッド getAddress を呼び出す。
結果はAPIによらずに等しく使えるように、下記の要素をもつ配列として戻す。エラー時には FALSE を返す。
添 字 内 容
address フォーマット済み住所
postalcode 郵便番号(一部サービスのみ)
prefecture 都道府県名
city 市町村名
local 市町村名以下

解説:緯度・経度を正規化

 177: /**
 178:  * 緯度・経度を正規化する
 179:  * @param   string $maps   緯度・経度表記
 180:  *            緯度(小数),経度(小数)
 181:  *            N緯度(度.分.秒)E(度.分.秒)
 182:  *            N緯度(度/分/秒)E(度/分/秒)
 183:  * @param   string $ingeo  入力データの測地系(tokyo:日本測地系,wgs84:世界測地系)
 184:  * @param   string $outgeo 出力データの測地系(tokyo:日本測地系,wgs84:世界測地系)
 185:  * @param   object $pgc    pahooGeoCodeクラス
 186:  * @return  array (緯度,経度)/FALSE=エラー
 187: */
 188: function parseGeo($maps, $ingeo, $outgeo, $pgc) {
 189:     //各種表記形式を小数表記に統一する
 190:     if (preg_match('/([0-9\.\+\-]+)[\,\/ ]+([0-9\.\+\-]+)/', $maps, $arr> 0) {
 191:         $v1 = $arr[1];
 192:         $v2 = $arr[2];
 193:     } else if (preg_match('/N([0-9]+)[\.\/]([0-9]*)[\.\/]?([0-9]*)[\.\/]?([0-9]*)/', $maps, $arr> 0) {
 194:         $v1 = $arr[1];
 195:         if (isset($arr[2]))     $v1 += ($arr[2] / 60);
 196:         if (isset($arr[3]))     $v1 += ($arr[3] / 3600);
 197:         if (isset($arr[4]))     $v1 += ($arr[4] / 36000);
 198:         if (preg_match('/E([0-9]+)[\.\/]([0-9]*)[\.\/]?([0-9]*)[\.\/]?([0-9]*)/', $maps, $arr> 0) {
 199:             $v2 = $arr[1];
 200:             if (isset($arr[2]))     $v2 += ($arr[2] / 60);
 201:             if (isset($arr[3]))     $v2 += ($arr[3] / 3600);
 202:             if (isset($arr[4]))     $v2 += ($arr[4] / 36000);
 203:         }
 204:     }
 205: 
 206:     //2桁の方を緯度、3桁の方を経度に
 207:     if ($v1 < 100)           $latitude  = $v1;
 208:     else if ($v1 >100)    $longitude = $v1;
 209:     if ($v2 < 100)           $latitude  = $v2;
 210:     else if ($v2 >100)    $longitude = $v2;
 211: 
 212:     //測地系の変換
 213:     if (preg_match('/tokyo/i', $ingeo> 0) {
 214:         if (preg_match('/wgs84/i', $outgeo> 0) {
 215:             list($latitude, $longitude) = $pgc->tokyo_wgs84($latitude, $longitude);
 216:         }
 217:     } else if (preg_match('/wgs84/i', $ingeo> 0) {
 218:         if (preg_match('/tokyo/i', $outgeo> 0) {
 219:             list($latitude, $longitude) = $pgc->wgs84_tokyo($latitude, $longitude);
 220:         }
 221:     }
 222: 
 223:     return array($latitude, $longitude);
 224: }

ユーザー関数 parseGeo は、入力された緯度・経度テキストを10進数(小数)に正規化し、必要に応じて測地系を変換する。

参考サイト

(この項おわり)
header