PHPで住所から緯度・経度を求める(Windowsアプリ版)

(1/1)
PHPでクラウド連携」で様々なプログラムを紹介しているが、PHPはWebアプリを作るのに便利な言語である。
そこで今回は、「PHPでGoogle等を利用して住所から緯度・経度を求める」で紹介した「Google Geocoding API V3」「ジオどすII」を利用し、住所や駅名から緯度・経度を求めるWindowsアプリケーションを作ってみることにする。

サンプル・プログラム

PHPで住所から緯度・経度を求める(Windowsアプリ版)

解説:準備

  23:  *      出典: 農研機構 (https://aginfo.cgk.affrc.go.jp/)
  24:  *  YOLP 標高API
  25:  *  YOLP 気象情報API
  26:  *  YOLPコンテンツジオコーダAPI
  27:  *  Yahoo! JavaScriptマップ【廃止】
  28:  *  HeartRails Geo API
  29:  *  OSM Nominatim

PHPでGoogle等を利用して住所から緯度・経度を求める」で紹介したクラス pahooGeoCode を利用する。

WebAPI「ジオどすII」ではAPIキーが必要になる。これは https://geodosu.com/user/register から無料で入手することができる。このAPIキーの値は定数 APIKEY_GEODOS にあらかじめ設定しておく。
また、今回は使用しないが、Yahoo! JAPAN Webサービスを利用する場合は、アプリケーションIDを https://account.edit.yahoo.co.jp/registration から無償取得し、定数 YAHOO_APPLICATION_ID に設定しておく。

解説:XMLパーシング

 107: 
 108:     return $version[0>5 ? TRUE : FALSE;
 109: }
 110: 
 111: /**
 112:  * PHP7以上かどうか検査する
 113:  * @return  bool TRUE:PHP5以上/FALSE:PHP5未満
 114: */
 115: function isphp7over() {
 116:     $version = explode('.', phpversion());
 117: 
 118:     return $version[0>7 ? TRUE : FALSE;
 119: }
 120: 
 121: /**
 122:  * 無効な証明書サイトからXML取得できるようにする
 123:  * @param   なし
 124:  * @return  なし
 125: */
 126: function unknown_certificate() {
 127:     $context = array(
 128:         'ssl' => array(
 129:             'verify_peer' => FALSE,
 130:             'verify_peer_name' => FALSE,
 131:         )
 132:     );
 133:     libxml_set_streams_context(stream_context_create($context));
 134: }
 135: 
 136: // GoogleMaps API Geocoding =================================================
 137: /**
 138:  * 指定XMLファイルを読み込んでDOMを返す
 139:  * @param   string $xml XMLファイル名
 140:  * @return  object DOMオブジェクト/NULL 失敗
 141: */
 142: function read_xml($xml) {
 143:     if ($this->isphp5over())    return NULL;
 144:     if (($fp = fopen($xml, 'r')) == FALSE)  return NULL;
 145: 
 146:     //いったん変数に読み込む
 147:     $str = fgets($fp);
 148:     $str = preg_replace('/UTF-8/', 'utf-8', $str);
 149: 
 150:     while (! feof($fp)) {
 151:         $str = $str . fgets($fp);
 152:     }
 153:     fclose($fp);
 154: 
 155:     //DOMを返す
 156:     $dom = domxml_open_mem($str);
 157:     if ($dom == NULL) {
 158:         echo "\n>Error while parsing the document - " . $xml . "\n";
 159:         exit(1);
 160:     }
 161: 
 162:     return $dom;
 163: }
 164: 
 165: /**
 166:  * GoogleMaps API Geocodingのformatted_addressから国名、郵便番号を除く
 167:  * @param   string $formatted_address 国名、郵便番号付き住所
 168:  * @return  string 住所のみ
 169: */
 170: function trimAddress($formatted_address) {
 171:     $pat1 = '/〒[0-9\-]+\s(.+)$/ui';
 172:     $pat2 = '/.+、(.+)$/ui';
 173: 
 174:     if (preg_match($pat1, $formatted_address, $arr> 0) {
 175:         $res = $arr[1];
 176:     } else if (preg_match($pat2, $formatted_address, $arr> 0) {
 177:         $res = $arr[1];
 178:     } else {
 179:         $res = $formatted_address;
 180:     }
 181: 
 182:     return $res;
 183: }
 184: 

PHPでGoogle等を利用して住所から緯度・経度を求める」で紹介したクラス pahooGeoCode は、そのままのプログラムでは bamcompile でコンパイルできない。
というのは、PHP4ではクラス DOMElement を使ってXMLパーシングしているのだが、これが "\Windows\System32\" に配置した "iconv.dll" をロードするためである。 bamcompile は、PHPエクテンション以外のDLLは配置できないのだ。
また、PHP4にはXMLをパーシングするための関数  xml_parse  があるのだが、これが使いにくい。

そこで、PEARにある XML_Unserializer を利用することにした。PEAP::XML_Unserializer は、XMLファイルの内容を連想配列に展開してくれる。

PEARのインストール方法は公式サイト「PEAR パッケージマネージャの取得とインストール」を参照していただくとして、ここで必要なのは、"PEAR.php", "Parser", "Unserializer" の3つだけである。
これを下記のように配置する。
address2geowin
│  address2geowin.bcp
└─address2geowin
     │  address2geowin.phpw
     │  address2geowin.rc
     │  address2geowin.ico
     │  PEAR.phpw
     │  Unserializer.php
     │  Parser.php
     │  php_mbstring.dll
     │  php_winbinder.dll
     ├─include
     │     wb_generic.inc.php
     │     wb_resources.inc.php
     │     wb_windows.inc.php
     │     winbinder.php
     └─icon
         address2geowin.ico
まず、 class_exists  を使って、クラス XML_Unserializer が存在していればオブジェクトを生成する。

メソッド getURL_GeoCodeAPI_V3 は「PHPでGoogle等を利用して住所から緯度・経度を求める」で紹介したものと同じで、APIの結果となるXMLのURLを取得する。
関数  file_get_contents  でXMLファイルを読み込み、メソッド unserialize を使ってアンシリアライズする。アンシリアライズした結果を配列 $arr に代入するのに、メソッド getUnserializedData を利用する。
あとは、APIが返すXML構造にしたがって配列 $arr を解釈していけばいい。

注意すべき点は、result が複数ある場合には $arr['result'][0]['geometry']$arr['result'][1]['geometry']$arr['result'][2]['geometry']‥‥のように代入されるが、result が1つしかない場合には $arr['result']['geometry'] となる点だ。
ここではif文で条件分岐して、どちらの場合も読み込めるようにしてある。

サンプル・プログラムの解説: 緯度・経度を表示

 104: /**
 105:  * 緯度・経度を表示
 106:  * @param  int      $window ウィンドウID
 107:  * @return string   なし
 108: */
 109: function put_geometry($window) {
 110:     $pgc = new pahooGeoCode();
 111: 
 112:     $items = array();
 113:     $query = wb_get_text(wb_get_control($window, IDC_ADDRESS_EDIT));
 114:     $query = sjis2internal($query);
 115:     list($n, $url) = $pgc->searchPoint2($query);
 116:     if (! $pgc->iserror()) {
 117:         for ($i = 1$i <$n$i++) {
 118:             list($items[$i]['latitude'], $items[$i]['longitude'], $items[$i]['address']) = $pgc->getPoint($i);
 119:         }
 120:         $msg = $items[1]['address'];
 121:         $lat = lat2dgree($items[1]['latitude']);
 122:         $lng = lng2dgree($items[1]['longitude']);
 123:     } else {
 124:         $msg = '**検索失敗**';
 125:         $lat = '';
 126:         $lng = '';
 127:     }
 128:     wb_set_text(wb_get_control($window, IDC_MSG_LABEL), internal2sjis($msg));
 129:     wb_set_text(wb_get_control($window, IDC_LAT_EDIT),  $lat); 
 130:     wb_set_text(wb_get_control($window, IDC_LNG_EDIT),  $lng); 
 131:     unset($items);
 132: 
 133:     $pgc = NULL;
 134: }

「生成」ボタンを押下したときの動作については、ネットに接続していなかったり、APIがエラーを返した場合を考慮し、エラーメッセージを変数 $msg に格納し、ラベルとして表示するようにしている。

コンパイル

コンパイルは「PHPでbamcompileを使ってEXEプログラムを生成」で紹介したのと同じ手順で、bamcompile.exe を使ってプロジェクトファイル "address2geowin.bcp" をコンパイルする。
コマンドラインから "bamcompile address2geowin.bcp" を実行する。コンパイルが完了すると、"address2geowin.exe" が生成されている。
"address2geowin.exe" は、DLL不要で、単独で動作するEXEプログラムである。

参考サイト

(この項おわり)
header