目次
- サンプル・プログラムの実行例
- サンプル・プログラム
- サンプル・プログラムの流れ
- 準備:pahooGeoCode クラス
- 準備:住所検索サービスの選択
- 「Google Geocoding API」による緯度・経度変換
- 解説:GoogleMaps API Geocoding
- 「YOLPコンテンツジオコーダAPI」による緯度・経度変換
- 解説:YOLPコンテンツジオコーダAPI
- 「HeartRails Geo API」による緯度・経度変換
- 解説:HeartRails Geo API
- 「OSM Nominatim Search API」による緯度・経度変換
- 解説:OSM Nominatim Search API
- 「国土地理院ジオコーディングAPI」による緯度・経度変換
- 解説:国土地理院ジオコーディングAPI
- 解説:検索と結果取得
- 解説:小数を指定した桁数で丸める
- 解説:メインプログラム
- 質疑応答
- 参考サイト
サンプル・プログラムの実行例
サンプル・プログラム
address2geo.php | サンプル・プログラム本体。 |
pahooGeoCode.php | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
5.5.0 | 2023/07/11 | 緯度・経度の小数点以下を指定桁数で丸め表示,検索キーの最小・最大長の指定 |
5.4.0 | 2023/07/02 | 国土地理院ジオコーディングAPIを追加 |
5.3 | 2021/09/18 | PHP8対応,リファラチェック改良,https化 |
5.2 | 2020/03/21 | OSM Nominatim Search API追加 |
5.1 | 2019/05/08 | HeartRails Geo API追加 |
バージョン | 更新日 | 内容 |
---|---|---|
6.3.1 | 2023/07/09 | bug-fix |
6.3.0 | 2023/07/02 | getPointsGSI()追加 |
6.2.0 | 2023/07/02 | ip2address()追加 |
6.1.0 | 2022/12/30 | ip2address()追加 |
6.0.4 | 2022/12/13 | PHP8.2対応 |
バージョン | 更新日 | 内容 |
---|---|---|
1.3.0 | 2023/07/11 | roundFloat() 追加 |
1.2.0 | 2023/04/22 | exitIfLessVersion() 追加 |
1.1.2 | 2023/02/05 | validString() 修正 |
1.11 | 2022/07/03 | isCommandLine() 修正 |
1.1 | 2022/06/04 | getValidString() 修正 |
サンプル・プログラムの流れ
準備: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 = '*****************************';
54:
55: //ジオどすII APIキー【廃止】
56: //http://geodosu.com/user/register
57: var $APIKEY_GEODOS = '*****************';
58:
59: //IP2Location.io APIキー
60: //https://www.ip2location.io/
61: //※IP2Location.ioを利用しないのなら登録不要
62: var $IP2LOCATION_API_KEY = '*****************';
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。
地図や住所検索として Google を利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。
準備:住所検索サービスの選択
58: //住所検索サービスの選択
59: // 0:Google
60: // 1:Yahoo!ジオコーダAPI
61: // 11:HeartRails Geo API
62: // 12:OSM Nominatim Search API
63: // 13:国土地理院ジオコーディングAPI
64: define('GEOSERVICE', 13);
値 | サービス名 | 制 約 |
---|---|---|
0 | 有料(決められた無料枠あり)。全世界の住所、ランドマークの検索可能。 | |
1 | Yahoo!JAPAN | 無料(?)。住所、ランドマーク、海外のどれを検索するか指定。ランドマークや海外地名検索はGoogleに劣る。 |
11 | HeartRails Geo API | 無料。住所、または住所の一部のみ検索可能。 |
12 | OSM Nominatim Search API | 無料。全世界の住所、ランドマークの検索可能。精度はGoogleに劣る。 |
13 | 国土地理院ジオコーディングAPI | 無料。日本国内の住所、ランドマークの検索可能。精度はGoogleに劣る。 |
「Google Geocoding API」による緯度・経度変換
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
URL |
---|
https://maps.googleapis.com/maps/api/geocode/xml |
フィールド名 | 要否 | 内 容 |
---|---|---|
key | 必須 | APIキー |
address | 必須 | 住所やランドマーク(UTF-8) |
language | 任意 | 使用言語。ja など |
sensor | 任意 | true または false |
解説:GoogleMaps API Geocoding
185: /**
186: * 指定した検索キーワードからGoogleMaps API Geocoding(V3) のURLを取得する.
187: * @param string $query 検索キーワード(UTF-8)
188: * @return string URL URL
189: */
190: function getURL_GeoCodeAPI_V3($query) {
191: $key = $this->GOOGLE_API_KEY_2;
192: return "https://maps.googleapis.com/maps/api/geocode/xml?key={$key}&language=ja®ion=JP&address=" . urlencode($query);
193: }
195: /**
196: * 指定した検索キーワードの緯度・経度を求める.
197: * クラウドサービスとしてGoogle Geocoding API(V3) を利用する.
198: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
199: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
200: * @param string $query 検索キーワード
201: * @param array $items 情報を格納する配列
202: * @return int ヒットした施設数/(-1):API呼び出し失敗
203: */
204: function getPointsV3_all($query, &$items) {
205: $url = $this->getURL_GeoCodeAPI_V3($query); //リクエストURL
206: $this->webapi = $url;
207: $n = 1;
208:
209: //PEAR::XML_Unserializer
210: if (class_exists('XML_Unserializer')) {
211: $xml = new XML_Unserializer();
212: $xml_data = file_get_contents($url);
213: $xml->unserialize($xml_data);
214: $arr = $xml->getUnserializedData();
215: //レスポンス・チェック
216: if (preg_match('/ok/i', $arr['status']) == 0) return (-1);
217: //位置情報
218: if (isset($arr['result']['geometry'])) {
219: $items[$n]['latitude'] = $arr['result']['geometry']['location']['lat'];
220: $items[$n]['longitude'] = $arr['result']['geometry']['location']['lng'];
221: $items[$n]['address'] = $this->trimAddress($arr['result']['formatted_address']);
222: $n++;
223: } else {
224: foreach ($arr['result'] as $val) {
225: $items[$n]['latitude'] = $val['geometry']['location']['lat'];
226: $items[$n]['longitude'] = $val['geometry']['location']['lng'];
227: $items[$n]['address'] = $this->trimAddress($val['formatted_address']);
228: $n++;
229: }
230: }
231: $xml = NULL;
232:
233: //PHP4用; DOM XML利用
234: } else if ($this->isphp5over() == FALSE) {
235: if (($dom = $this->read_xml($url)) == NULL) return FALSE;
236: $gr = $dom->get_elements_by_tagname('GeocodeResponse');
237: //レスポンス・チェック
238: $res = $gr[0]->get_elements_by_tagname('status');
239: if (preg_match("/ok/i", $res[0]->get_content()) == 0) return 0;
240: //位置情報
241: $res = $gr[0]->get_elements_by_tagname('result');
242: foreach ($res as $val) {
243: $geo = $val->get_elements_by_tagname('geometry');
244: $loc = $geo[0]->get_elements_by_tagname('location');
245: $lat = $loc[0]->get_elements_by_tagname('lat');
246: $items[$n]['latitude'] = (double)$lat[0]->get_content();
247: $lng = $loc[0]->get_elements_by_tagname('lng');
248: $items[$n]['longitude'] = (double)$lng[0]->get_content();
249: $addr = $val->get_elements_by_tagname('formatted_address');
250: $items[$n]['address'] = $this->trimAddress((string)$addr[0]->get_content());
251: $n++;
252: }
253: //PHP5用; SimpleXML利用
254: } else {
255: $this->unknown_certificate();
256: $res = simplexml_load_file($url);
257: //レスポンス・チェック
258: if (preg_match("/ok/i", $res->status) == 0) return 0;
259: foreach ($res->result as $element) {
260: $items[$n]['latitude'] = (double)$element->geometry->location->lat;
261: $items[$n]['longitude'] = (double)$element->geometry->location->lng;
262: $items[$n]['address'] = $this->trimAddress((string)$element->formatted_address);
263: $n++;
264: }
265: }
266: return ($n - 1);
267: }
検索結果が複数ある場合に備え、緯度・経度・人間が読める住所のセットを、連想配列のプロパティ $items に格納しておく。
「YOLPコンテンツジオコーダAPI」による緯度・経度変換
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
URL |
---|
https://map.yahooapis.jp/geocode/cont/V1/contentsGeoCoder |
フィールド名 | 要否 | 内 容 |
---|---|---|
appid | 必須 | アプリケーションID |
query | 必須 | 住所やランドマーク |
ei | 任意 | 文字エンコード:UTF-8(デフォルト)/EUC-JP/SJISなど |
category | 任意 | 検索対象カテゴリ:address(デフォルト)/landmark/world |
results | 任意 | 表示件数:最大10(デフォルト) |
output | 任意 | 出力形式:xml(デフォルト)/json |
callback | 任意 | JSONPとして出力する際のコールバック関数名を入力するためのパラメータ。UTF-8でエンコードした文字列を入力する。 |
解説:YOLPコンテンツジオコーダAPI
1250: /**
1251: * 指定した検索キーワードからYOLPコンテンツジオコーダAPIのURLを取得する.
1252: * @param string $query 検索キーワード(UTF-8)
1253: * @param string $category 検索対象カテゴリ
1254: * address = 住所(省略時)
1255: * landmark = ランドマーク
1256: * world = 世界
1257: * @return string URL リクエストURL
1258: */
1259: function getURL_YOLP_GeoCoder($query, $category='address') {
1260: $appid = $this->YAHOO_APPLICATION_ID;
1261: return "https://map.yahooapis.jp/geocode/cont/V1/contentsGeoCoder?appid={$appid}&el=UTF-8&output=xml&category={$category}&query=" . urlencode($query);
1262: }
1264: /**
1265: * 指定した検索キーワードの緯度・経度を求める.
1266: * クラウドサービスとしてYOLPコンテンツジオコーダAPIを利用する.
1267: * $categoryに検索対象カテゴリをセットする(省略時は'address').
1268: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1269: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1270: * @param string $query 検索キーワード
1271: * @param array $items 情報を格納する配列
1272: * @param string $category 検索対象カテゴリ
1273: * address = 住所(省略時)
1274: * landmark = ランドマーク
1275: * world = 世界
1276: * @return int ヒットした施設数/(-1):API呼び出し失敗
1277: */
1278: function getPointsYOLP_all($query, &$items, $category='address') {
1279: $url = $this->getURL_YOLP_GeoCoder($query, $category); //リクエストURL
1280: $this->webapi = $url;
1281: $n = 1;
1282:
1283: $this->unknown_certificate();
1284: $res = simplexml_load_file($url);
1285: //レスポンス・チェック
1286: if (!isset($res->ResultInfo)) return (-1);
1287: if (isset($res->ResultInfo->Total) && ((int)$res->ResultInfo->Total <= 0)) return 0; //v.5.73追加
1288:
1289: foreach ($res->Feature as $element) {
1290: if (preg_match('/([\-0-9\.]+)\,([\-0-9\.]+)/i', $element->Geometry->Coordinates, $arr) > 0) {
1291: if (isset($arr[1]) && isset($arr[2])) {
1292: $items[$n]['latitude'] = (double)$arr[2];
1293: $items[$n]['longitude'] = (double)$arr[1];
1294: $items[$n]['address'] = (string)$element->Property->Address;
1295: $n++;
1296: }
1297: }
1298: }
1299:
1300: return ($n - 1);
1301: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $items に格納しておく。
1303: /**
1304: * YOLPコンテンツジオコーダAPI のカテゴリ選択ラジオボタンの生成
1305: * @param string $name HTML name
1306: * @param string $default デフォルト値(省略可能)
1307: * @return string HTML
1308: */
1309: function makeYOLP_GeoSelectCategory($name, $default='') {
1310: //デフォルト値設定
1311: if (isset($this->YOLP_GeoCategory[$default])) {
1312: foreach ($this->YOLP_GeoCategory as $key=>$item) {
1313: $item[$key]['checked'] = '';
1314: }
1315: $this->YOLP_GeoCategory[$default]['checked'] = 'checked';
1316: }
1317: //選択ラジオボタンの生成
1318: $html = '';
1319: $i = 1;
1320: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1321: $html .= "<input type=\"radio\" name=\"{$name}\" value=\"{$key}\" {$val['checked']} />{$val['title']} ";
1322: $i++;
1323: }
1324: return $html;
1325: }
1335: /**
1336: * checkedされているカテゴリを検索する
1337: * @return string 選択された関数名/FALSE=checkedされている処理がない
1338: */
1339: function getYOLP_GeoSelectCategory() {
1340: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1341: if ($val['checked'] == 'checked') return $key;
1342: }
1343:
1344: return FALSE;
1345: }
1347: /**
1348: * カテゴリをchekedする
1349: * @param string $val カテゴリ値
1350: * @return bool TRUE/FALSE
1351: */
1352: function setYOLP_GeoSelectCategory($val) {
1353: $old = $this->getYOLP_GeoSelectCategory();
1354: if ($val != FALSE) $this->YOLP_GeoCategory[$old]['checked'] = '';
1355: $this->YOLP_GeoCategory[$val]['checked'] = 'checked';
1356:
1357: return TRUE;
1358: }
「HeartRails Geo API」による緯度・経度変換
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
URL |
---|
https://geoapi.heartrails.com/api/xml?method=suggest |
フィールド名 | 要否 | 内 容 |
---|---|---|
method | 必須 | メソッド名:suggest(固定) |
keyword | 必須 | 検索キーワード(UTF-8でURLエンコード) |
matching | 必須 | prefix(前方一致)、like(部分一致)、suffix(後方一致)のいずれか |
解説:HeartRails Geo API
1494: /**
1495: * 指定した検索キーワードの緯度・経度を求める.
1496: * クラウドサービスとしてHeartRails Geo APIの住所検索APIを利用する.
1497: * 検索方式は$matchingにセットする(省略時は'like').
1498: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1499: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1500: * @param string $query 検索キーワード:住所のみ(UTF-8)
1501: * @param array $items 情報を格納する配列
1502: * @param string $matching 検索方式
1503: * prefix = 前方一致
1504: * like = 部分一致(省略時)
1505: * suffix = 後方一致
1506: * @return int ヒットした地点数/(-1):API呼び出し失敗
1507: */
1508: function getPointsHeartRailsGeo_all($query, &$items, $matching='like') {
1509: //リクエストURL
1510: $url = "https://geoapi.heartrails.com/api/xml?method=suggest&matching={$matching}&keyword=" . urlencode($query);
1511: $this->webapi = $url;
1512: $n = 1;
1513:
1514: $this->unknown_certificate();
1515: $res = simplexml_load_file($url);
1516: //レスポンス・チェック
1517: if (isset($res->error)) {
1518: $this->error = TRUE;
1519: $this->errmsg = (string)$res->error;
1520: $n = 0;
1521: } else if (! isset($res->location)) {
1522: $this->error = TRUE;
1523: $this->errmsg = 'Not found';
1524: $n = 1;
1525: } else {
1526: foreach ($res->location as $element) {
1527: $items[$n]['latitude'] = (double)$element->y;
1528: $items[$n]['longitude'] = (double)$element->x;
1529: $items[$n]['prefecture'] = (string)$element->prefecture;
1530: $items[$n]['city'] = (string)$element->city;
1531: $items[$n]['city_kana'] = (string)$element->{'city-kana'};
1532: $items[$n]['town'] = (string)$element->town;
1533: $items[$n]['town_kana'] = (string)$element->{'town-kana'};
1534: $items[$n]['postal'] = (string)$element->postal;
1535: $items[$n]['address'] = (string)$element->prefecture . (string)$element->city . (string)$element->town;
1536: $n++;
1537: }
1538: }
1539:
1540: return ($n - 1);
1541: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $items に格納しておく。
「OSM Nominatim Search API」による緯度・経度変換
URL |
---|
https://nominatim.openstreetmap.org/search |
フィールド名 | 要否 | 内 容 |
---|---|---|
format | 任意 | 出力形式。html|xml|json|jsonv2。省略時はhtml |
q | 必須 | 住所やランドマーク(UTF-8) |
json_callback | 任意 | json の出力をラップするコールバック関数(JSONP) |
addressdetails | 任意 | 住所の要素への細分化を含むかどうか。0|1。省略時は0 |
解説:OSM Nominatim Search API
1734: /**
1735: * 指定した検索キーワードの緯度・経度を求める.
1736: * クラウドサービスとしてOSM Nominatim Search API住所検索APIを利用する.
1737: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1738: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1739: * @param string $query 検索キーワード:住所のみ(UTF-8)
1740: * @param array $items 情報を格納する配列
1741: * @return int ヒットした地点数/(-1):API呼び出し失敗
1742: */
1743: function getPointsNominatim_all($query, &$items) {
1744: //リクエストURL
1745: $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . urlencode($query);
1746: $this->webapi = $url;
1747: $n = 1;
1748:
1749: //User-Agent偽装
1750: $header = array(
1751: 'Content-Type: application/x-www-form-urlencoded',
1752: 'User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1'
1753: );
1754: $stream = stream_context_create(array(
1755: 'http' => array(
1756: 'method' => 'GET',
1757: 'header' => implode("\r\n", $header),
1758: 'ignore_errors'=>TRUE
1759: )
1760: ));
1761: $json = file_get_contents($url, FALSE, $stream);
1762:
1763: //レスポンス・チェック
1764: if ($json == FALSE) {
1765: $this->error = TRUE;
1766: $this->errmsg = '';
1767: $n = 0;
1768: } else {
1769: if ($this->isphp7over()) {
1770: $res = @json_decode($json, FALSE, 512, JSON_BIGINT_AS_STRING);
1771: } else {
1772: $res = @json_decode($json, FALSE, 512);
1773: }
1774: foreach ($res as $element) {
1775: $items[$n]['latitude'] = (double)$element->lat;
1776: $items[$n]['longitude'] = (double)$element->lon;
1777: $items[$n]['address'] = (string)$element->display_name;
1778: $n++;
1779: }
1780: }
1781: if ($n == 1) {
1782: $this->error = TRUE;
1783: $this->errmsg = 'Not found';
1784: }
1785:
1786: return ($n - 1);
1787: }
クラウドサービスの呼び出し時、User-Agent を設定する目的で、 stream_context_create 関数を利用し、 file_get_contents 関数を呼び出している。
json_decode 関数の呼び出しは、BIGINTの扱いが異なるPHP 7以上と未満で場合分けしている。
検索結果が複数ある場合に備え、緯度・経度・人間が読める住所のセットを、連想配列のプロパティ $items に格納しておく。
「国土地理院ジオコーディングAPI」による緯度・経度変換
なお、国土地理院によると、この機能は主に地理院地図からの利用を想定しているものであり、必ずしも常にまた長期的に提供できるとは限らないし、仕様や利用方法が予告なく変更する場合があるとアナウンスしている。
URL |
---|
https://msearch.gsi.go.jp/address-search/AddressSearch |
フィールド名 | 要否 | 内 容 |
---|---|---|
q | 必須 | 住所やランドマーク(UTF-8) |
解説:国土地理院ジオコーディングAPI
1790: /**
1791: * 指定した検索キーワードの緯度・経度を求める.
1792: * クラウドサービスとして国土地理院ジオコーディングAPIを利用する.
1793: * 検索方式は$matchingにセットする(省略時は'like').
1794: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1795: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1796: * @param string $query 検索キーワード:住所のみ(UTF-8)
1797: * @param array $items 情報を格納する配列
1798: * @return int ヒットした地点数/(-1):API呼び出し失敗
1799: */
1800: function getPointsGSI($query, &$items) {
1801: //リクエストURL
1802: $url = "https://msearch.gsi.go.jp/address-search/AddressSearch?q=" . urlencode($query);
1803: $this->webapi = $url;
1804: $n = 1;
1805:
1806: $this->unknown_certificate();
1807: $json = file_get_contents($url);
1808: //レスポンス・チェック
1809: if ($json == FALSE) {
1810: $this->error = TRUE;
1811: $this->errmsg = '国土地理院ジオコーディングAPIが応答しません';
1812: $n = 0;
1813: } else {
1814: $arr = json_decode($json);
1815: if (count($arr) == 0) {
1816: $this->error = TRUE;
1817: $this->errmsg = '住所が見つかりません';
1818: $n = 0;
1819: } else {
1820: foreach ($arr as $element) {
1821: $items[$n]['latitude'] = (double)$element->geometry->coordinates[1];
1822: $items[$n]['longitude'] = (double)$element->geometry->coordinates[0];
1823: $items[$n]['address'] = (string)$element->properties->title;
1824: $items[$n]['postal'] = (string)$element->properties->addressCode;
1825: $n++;
1826: }
1827: }
1828: }
1829:
1830: return ($n - 1);
1831: }
解説:検索と結果取得
2198: /**
2199: * 指定した検索キーワードの緯度・経度を求める.
2200: * クラウドサービスとしてGoogle Geocoding API, Yahoo!ジオコーダAPI,
2201: * HeartRails Geo API, OSM Nominatim Search API,
2202: * 国土地理院ジオコーディングAPIを指定できる.
2203: * Yahoo!ジオコーダAPIを利用する場合は,検索対象カテゴリ$categoryをセットする.
2204: * (省略時は 'like')
2205: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
2206: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
2207: *
2208: * @param string $query 検索キーワード(UTF-8)
2209: * @param int $api 0:Google Geocoding API(省略時)
2210: * 1:Yahoo!ジオコーダAPI
2211: * 11:HeartRails Geo API
2212: * 12:OSM Nominatim Search API
2213: * 13:国土地理院ジオコーディングAPI
2214: * @param string $category 検索対象カテゴリ(YOLPのみ必要)
2215: * address = 住所(省略時)
2216: * landmark = ランドマーク
2217: * world = 世界
2218: * @return array(int ヒットした地点数,string WebAPI)
2219: */
2220: function searchPoint3($query, $api=0, $category='address') {
2221: static $pat1 = '/E(\d+\.?\d*)N(\d+\.?\d*)/i';
2222: static $pat2 = '/E(\d+)\.(\d+)\.(\d+)\.(\d+)N(\d+)\.(\d+)\.(\d+)\.(\d+)/i';
2223:
2224: unset($this->items);
2225: $this->items = array();
2226: $this->hits = 0;
2227:
2228: //緯度・経度表記(1)
2229: if (preg_match($pat1, $query) > 0) {
2230: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2231: $this->parse_geo($query);
2232: $this->items[1]['address'] = '';
2233: $this->hits = 1;
2234:
2235: //緯度・経度表記(2)
2236: } else if (preg_match($pat2, $query) > 0) {
2237: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2238: $this->parse_geo($query);
2239: $this->items[1]['address'] = '';
2240: $this->hits = 1;
2241:
2242: //Google Geocoding API使用
2243: } else if ($api == 0) {
2244: $n = $this->getPointsV3_all($query, $this->items);
2245: if ($n == (-1)) { //v.5.73修正
2246: $this->error = TRUE;
2247: $this->errmsg = 'Google Geocoding APIにトラブル発生';
2248: $this->hits = 0;
2249: } else if ($n == 0) {
2250: $this->error = TRUE;
2251: $this->errmsg = '指定キーワードでは検索できない';
2252: $this->hits = 0;
2253: } else {
2254: $this->hits = $n;
2255: }
2256:
2257: //Yahoo!ジオコーダAPI使用
2258: } else if ($api == 1) {
2259: $n = $this->getPointsYOLP_all($query, $this->items, $category);
2260: if ($n == (-1)) { //v.5.73修正
2261: $this->error = TRUE;
2262: $this->errmsg = 'Yahoo!ジオコーダAPIにトラブル発生';
2263: $this->hits = 0;
2264: } else if ($n == 0) {
2265: $this->error = TRUE;
2266: $this->errmsg = '指定キーワードでは検索できない';
2267: $this->hits = 0;
2268: } else {
2269: $this->hits = $n;
2270: }
2271:
2272: //HeartRails Geo API使用
2273: } else if ($api == 11) {
2274: $n = $this->getPointsHeartRailsGeo_all($query, $this->items, 'like');
2275: if ($n == (-1)) { //v.5.73修正
2276: $this->hits = 0;
2277: } else if ($n == 0) {
2278: $this->errmsg = '指定キーワードでは検索できない';
2279: $this->hits = 0;
2280: } else {
2281: $this->hits = $n;
2282: }
2283:
2284: //OSM Nominatim Search API使用
2285: } else if ($api == 12) {
2286: $n = $this->getPointsNominatim_all($query, $this->items);
2287: if ($n == (-1)) {
2288: $this->errmsg = 'OSM Nominatim Search APIにトラブル発生';
2289: $this->hits = 0;
2290: } else if ($n == 0) {
2291: $this->errmsg = '指定キーワードでは検索できない';
2292: $this->hits = 0;
2293: } else {
2294: $this->hits = $n;
2295: }
2296:
2297: //国土地理院ジオコーディングAPIs使用
2298: } else if ($api == 13) {
2299: $n = $this->getPointsGSI($query, $this->items);
2300: if ($n > 0) {
2301: $this->hits = $n;
2302: }
2303:
2304: //エラー
2305: } else {
2306: $this->error = TRUE;
2307: $this->errmsg = 'ジオコーダーAPIの指定間違い';
2308: $this->hits = 0;
2309: }
2310:
2311: return array($this->hits, $this->webapi);
2312: }
結果はプロパティ $items に格納する。戻り値としてヒットした件数を返す。
334: /**
335: * 検索結果(緯度・経度)を取得
336: * @param int $id 取得したい地点番号
337: * @return array(緯度,経度,住所):世界測地系
338: */
339: function getPoint($id) {
340: if ($id <= 0 || $id > $this->hits) {
341: $this->error = TRUE;
342: $this->errmsg = '不正な地点番号';
343: $latitude = FALSE;
344: $longitude = FALSE;
345: $address = FALSE;
346: } else {
347: $this->error = FALSE;
348: $this->errmsg = '';
349: $latitude = $this->items[$id]['latitude'];
350: $longitude = $this->items[$id]['longitude'];
351: $address = $this->items[$id]['address'];
352: }
353:
354: return array($latitude, $longitude, $address);
355: }
解説:小数を指定した桁数で丸める
437: /**
438: * 小数を指定した桁数で丸めて文字列として返す。
439: * 与えた小数の有効桁数より指定桁数が多いときには,末尾に0をサプレスする.
440: * @param float $x 丸めたい小数
441: * @param int $dp 小数点以下の桁数(0:整数,負数:丸めない)
442: * @return string 丸めた結果
443: */
444: function roundFloat($x, $dp) {
445: //丸めない
446: if ($dp < 0) {
447: $y = sprintf('%f', $x);
448: //整数に丸める
449: } else if ($dp == 0) {
450: $y = sprintf('%d', $x);
451: //指定した桁数に丸める
452: } else {
453: $ft = '%.' . (int)$dp . 'f';
454: $y = sprintf($ft, $x);
455: }
456: return (string)$y;
457: }
組み込み関数 sprintf を利用し、小数を指定した桁数で丸めて文字列として返す。与えた小数の有効桁数より指定桁数が多いときには、末尾に0をサプレスする。
解説:メインプログラム
66: //初期値
67: define('DEF_QUERY', '東京都千代田区丸の内一丁目'); //検索キー
68: define('DEF_CATEGORY', 'address'); //カテゴリ
69:
70: //表示幅(ピクセル)
71: define('WIDTH', 600);
72:
73: //緯度・経度の小数点以下表示桁数(0:整数に丸める,負数:丸めない)
74: define('DECIMAL_POINT', 6);
75:
76: //検索キーの最小文字長
77: define('QUERY_MIN_LEN', 3);
78:
79: //検索キーの最大文字長
80: define('QUERY_MAX_LEN', 99);
81:
82: //住所・緯度・経度に関わるクラス:include_pathに配置すること
83: require_once('pahooGeoCode.php');
質疑応答
国土地理院のジオコーディングはお試しになっていたと思いますが、なぜ利用されて居なかったのでしょうか? 精度でしょうか?(ヨッシーXX様,2023年6月30日)【回答】
有用な情報をありがとうございます。試していませんでした。近いうちに試してみて、プログラムから利用できるようにしようと思います。
これらサービスのうち Google は全世界を対象として最も精度の高い検索が可能だが、有料サービスに移行したため(無料枠あり)、その他の無料利用できるサービスを選択できるようにしている。
ぱふぅ家のホームページで紹介するプログラムの住所検索機能は、すべてこのクラス pahooGeoCode を流用している。
(2023年7月11日)緯度・経度の小数点以下を指定桁数で丸めて表示できるようにした.検索キーの最小・最大長の指定ができるようにした.
(2023年7月2日)国土地理院ジオコーディングAPIを利用できるようにした.