目次
- サンプル・プログラムの実行例
- サンプル・プログラム
- サンプル・プログラムの流れ
- 準備: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.6.0 | 2025/08/24 | .pahooEnv導入 |
| 5.5.1 | 2024/09/14 | searchPoint3() -- エラー対策追加 |
| 5.5.0 | 2023/07/11 | 緯度・経度の小数点以下を指定桁数で丸め表示,検索キーの最小・最大長の指定 |
| 5.4.0 | 2023/07/02 | 国土地理院ジオコーディングAPIを追加 |
| 5.3 | 2021/09/18 | PHP8対応,リファラチェック改良,https化 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 6.9.1 | 2025/11/25 | PHP8.5対応:double→float |
| 6.9.0 | 2025/09/21 | jsPolygon, jsPolygon_Gmap, jsPolygon_Leaflet, loadGeoJSON, getPrefBorderList を追加 |
| 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 追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 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 の https対応
Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dllLinuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順
これで準備は完了だ。
準備:pahooGeoCode クラス
pahooGeoCode.php
41: class pahooGeoCode {
42: public $items; // 検索結果格納用
43: public $error; // エラー・フラグ
44: public $errmsg; // エラー・メッセージ
45: public $hits; // 検索ヒット件数
46: public $webapi; // 直前に呼び出したWebAPI URL
47:
48: // 都道府県境界線データ
49: // SimpleMaps.com is a product of Pareto Software, LLC. © 2010-2025
50: // https://simplemaps.com/gis/country/jp
51: // ※各自の環境に合わせて設定すること
52: public $GeoJsonJP = __DIR__ . '/jp.json';
53:
54: // -- 以下のデータは .env ファイルに記述可能
55: // Google Cloud Platform APIキー
56: // https://cloud.google.com/maps-platform/
57: // ※Google Maps APIを利用しないのなら登録不要
58: public $GOOGLE_API_KEY_1 = ''; // HTTPリファラ用
59: public $GOOGLE_API_KEY_2 = ''; // IP制限用
60: public $GOOGLE_MAP_ID = ''; // GoogleMaps ID
61:
62: // Yahoo! JAPAN Webサービス アプリケーションID
63: // https://e.developer.yahoo.co.jp/register
64: // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
65: public $YAHOO_APPLICATION_ID = '';
66:
67: // OSM Nominatim Search API利用時に知らせるメールアドレス
68: // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
69: // ※OSM Nominatim Search APIを利用しないのなら登録不要
70: public $NOMINATIM_EMAIL = '';
71:
72: // IP2Location.io APIキー
73: // https://www.ip2location.io/
74: // ※IP2Location.ioを利用しないのなら登録不要
75: public $IP2LOCATION_API_KEY = '';
地図や住所検索として 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 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備:住所検索サービスの選択
address2geo.php
60: // 住所検索サービスの選択
61: // 0:Google
62: // 1:Yahoo!ジオコーダAPI
63: // 11:HeartRails Geo API
64: // 12:OSM Nominatim Search API
65: // 13:国土地理院ジオコーディングAPI
66: define('GEOSERVICE', 12);
| 値 | サービス名 | 制 約 |
|---|---|---|
| 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
pahooGeoCode.php
218: /**
219: * 指定した検索キーワードからGoogleMaps API Geocoding(V3) のURLを取得する.
220: * @param string $query 検索キーワード(UTF-8)
221: * @return string URL URL
222: */
223: function getURL_GeoCodeAPI_V3($query) {
224: $key = $this->GOOGLE_API_KEY_2;
225: return "https://maps.googleapis.com/maps/api/geocode/xml?key={$key}&language=ja®ion=JP&address=" . urlencode($query);
226: }
pahooGeoCode.php
228: /**
229: * 指定した検索キーワードの緯度・経度を求める.
230: * クラウドサービスとしてGoogle Geocoding API(V3) を利用する.
231: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
232: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
233: * @param string $query 検索キーワード
234: * @param array $items 情報を格納する配列
235: * @return int ヒットした施設数/(-1):API呼び出し失敗
236: */
237: function getPointsV3_all($query, &$items) {
238: $url = $this->getURL_GeoCodeAPI_V3($query); // リクエストURL
239: $this->webapi = $url;
240: $n = 1;
241:
242: // PEAR::XML_Unserializer
243: if (class_exists('XML_Unserializer')) {
244: $xml = new XML_Unserializer();
245: $xml_data = file_get_contents($url);
246: $xml->unserialize($xml_data);
247: $arr = $xml->getUnserializedData();
248: // レスポンス・チェック
249: if (preg_match('/ok/i', $arr['status']) == 0) return (-1);
250: // 位置情報
251: if (isset($arr['result']['geometry'])) {
252: $items[$n]['latitude'] = $arr['result']['geometry']['location']['lat'];
253: $items[$n]['longitude'] = $arr['result']['geometry']['location']['lng'];
254: $items[$n]['address'] = $this->trimAddress($arr['result']['formatted_address']);
255: $n++;
256: } else {
257: foreach ($arr['result'] as $val) {
258: $items[$n]['latitude'] = $val['geometry']['location']['lat'];
259: $items[$n]['longitude'] = $val['geometry']['location']['lng'];
260: $items[$n]['address'] = $this->trimAddress($val['formatted_address']);
261: $n++;
262: }
263: }
264: $xml = NULL;
265:
266: // PHP4用; DOM XML利用
267: } else if ($this->isphp5over() == FALSE) {
268: if (($dom = $this->read_xml($url)) == NULL) return FALSE;
269: $gr = $dom->get_elements_by_tagname('GeocodeResponse');
270: // レスポンス・チェック
271: $res = $gr[0]->get_elements_by_tagname('status');
272: if (preg_match("/ok/i", $res[0]->get_content()) == 0) return 0;
273: // 位置情報
274: $res = $gr[0]->get_elements_by_tagname('result');
275: foreach ($res as $val) {
276: $geo = $val->get_elements_by_tagname('geometry');
277: $loc = $geo[0]->get_elements_by_tagname('location');
278: $lat = $loc[0]->get_elements_by_tagname('lat');
279: $items[$n]['latitude'] = (float)$lat[0]->get_content();
280: $lng = $loc[0]->get_elements_by_tagname('lng');
281: $items[$n]['longitude'] = (float)$lng[0]->get_content();
282: $addr = $val->get_elements_by_tagname('formatted_address');
283: $items[$n]['address'] = $this->trimAddress((string)$addr[0]->get_content());
284: $n++;
285: }
286: // PHP5用; SimpleXML利用
287: } else {
288: $this->unknown_certificate();
289: $res = simplexml_load_file($url);
290: // レスポンス・チェック
291: if (preg_match("/ok/i", $res->status) == 0) return 0;
292: foreach ($res->result as $element) {
293: $items[$n]['latitude'] = (float)$element->geometry->location->lat;
294: $items[$n]['longitude'] = (float)$element->geometry->location->lng;
295: $items[$n]['address'] = $this->trimAddress((string)$element->formatted_address);
296: $n++;
297: }
298: }
299: return ($n - 1);
300: }
検索結果が複数ある場合に備え、緯度・経度・人間が読める住所のセットを、連想配列のプロパティ $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
pahooGeoCode.php
1414: /**
1415: * 指定した検索キーワードからYOLPコンテンツジオコーダAPIのURLを取得する.
1416: * @param string $query 検索キーワード(UTF-8)
1417: * @param string $category 検索対象カテゴリ
1418: * address = 住所(省略時)
1419: * landmark = ランドマーク
1420: * world = 世界
1421: * @return string URL リクエストURL
1422: */
1423: function getURL_YOLP_GeoCoder($query, $category='address') {
1424: $appid = $this->YAHOO_APPLICATION_ID;
1425: return "https://map.yahooapis.jp/geocode/cont/V1/contentsGeoCoder?appid={$appid}&el=UTF-8&output=xml&category={$category}&query=" . urlencode($query);
1426: }
pahooGeoCode.php
1428: /**
1429: * 指定した検索キーワードの緯度・経度を求める.
1430: * クラウドサービスとしてYOLPコンテンツジオコーダAPIを利用する.
1431: * $categoryに検索対象カテゴリをセットする(省略時は'address').
1432: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1433: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1434: * @param string $query 検索キーワード
1435: * @param array $items 情報を格納する配列
1436: * @param string $category 検索対象カテゴリ
1437: * address = 住所(省略時)
1438: * landmark = ランドマーク
1439: * world = 世界
1440: * @return int ヒットした施設数/(-1):API呼び出し失敗
1441: */
1442: function getPointsYOLP_all($query, &$items, $category='address') {
1443: $url = $this->getURL_YOLP_GeoCoder($query, $category); // リクエストURL
1444: $this->webapi = $url;
1445: $n = 1;
1446:
1447: $this->unknown_certificate();
1448: $res = simplexml_load_file($url);
1449: // レスポンス・チェック
1450: if (!isset($res->ResultInfo)) return (-1);
1451: if (isset($res->ResultInfo->Total) && ((int)$res->ResultInfo->Total <= 0)) return 0; // v.5.73追加
1452:
1453: foreach ($res->Feature as $element) {
1454: if (preg_match('/([\-0-9\.]+)\,([\-0-9\.]+)/i', $element->Geometry->Coordinates, $arr) > 0) {
1455: if (isset($arr[1]) && isset($arr[2])) {
1456: $items[$n]['latitude'] = (float)$arr[2];
1457: $items[$n]['longitude'] = (float)$arr[1];
1458: $items[$n]['address'] = (string)$element->Property->Address;
1459: $n++;
1460: }
1461: }
1462: }
1463:
1464: return ($n - 1);
1465: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $items に格納しておく。
pahooGeoCode.php
1467: /**
1468: * YOLPコンテンツジオコーダAPI のカテゴリ選択ラジオボタンの生成
1469: * @param string $name HTML name
1470: * @param string $default デフォルト値(省略時は空文字)
1471: * @param string $flagWorld 世界を選択できるようにする(省略時はTRUE)
1472: * @return string HTML
1473: */
1474: function makeYOLP_GeoSelectCategory($name, $default='', $flagWorld=TRUE) {
1475: // デフォルト値設定
1476: if (isset($this->YOLP_GeoCategory[$default])) {
1477: foreach ($this->YOLP_GeoCategory as $key=>$item) {
1478: $item[$key]['checked'] = '';
1479: }
1480: $this->YOLP_GeoCategory[$default]['checked'] = 'checked';
1481: }
1482: // 選択ラジオボタンの生成
1483: $html = '';
1484: $i = 1;
1485: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1486: if (! $flagWorld && ($key == 'world')) continue;
1487: $html .= "<input type=\"radio\" name=\"{$name}\" value=\"{$key}\" {$val['checked']} />{$val['title']} ";
1488: $i++;
1489: }
1490: return $html;
1491: }
pahooGeoCode.php
1501: /**
1502: * checkedされているカテゴリを検索する
1503: * @return string 選択された関数名/FALSE=checkedされている処理がない
1504: */
1505: function getYOLP_GeoSelectCategory() {
1506: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1507: if ($val['checked'] == 'checked') return $key;
1508: }
1509:
1510: return FALSE;
1511: }
pahooGeoCode.php
1513: /**
1514: * カテゴリをchekedする
1515: * @param string $val カテゴリ値
1516: * @return bool TRUE/FALSE
1517: */
1518: function setYOLP_GeoSelectCategory($val) {
1519: $old = $this->getYOLP_GeoSelectCategory();
1520: if ($val != FALSE) $this->YOLP_GeoCategory[$old]['checked'] = '';
1521: $this->YOLP_GeoCategory[$val]['checked'] = 'checked';
1522:
1523: return TRUE;
1524: }
「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
pahooGeoCode.php
1562: /**
1563: * 指定した検索キーワードの緯度・経度を求める.
1564: * クラウドサービスとしてHeartRails Geo APIの住所検索APIを利用する.
1565: * 検索方式は$matchingにセットする(省略時は'like').
1566: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1567: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1568: * @param string $query 検索キーワード:住所のみ(UTF-8)
1569: * @param array $items 情報を格納する配列
1570: * @param string $matching 検索方式
1571: * prefix = 前方一致
1572: * like = 部分一致(省略時)
1573: * suffix = 後方一致
1574: * @return int ヒットした地点数/(-1):API呼び出し失敗
1575: */
1576: function getPointsHeartRailsGeo_all($query, &$items, $matching='like') {
1577: // リクエストURL
1578: $url = "https://geoapi.heartrails.com/api/xml?method=suggest&matching={$matching}&keyword=" . urlencode($query);
1579: $this->webapi = $url;
1580: $n = 1;
1581:
1582: $this->unknown_certificate();
1583: $res = simplexml_load_file($url);
1584: // レスポンス・チェック
1585: if (isset($res->error)) {
1586: $this->error = TRUE;
1587: $this->errmsg = (string)$res->error;
1588: $n = 0;
1589: } else if (! isset($res->location)) {
1590: $this->error = TRUE;
1591: $this->errmsg = 'Not found';
1592: $n = 1;
1593: } else {
1594: foreach ($res->location as $element) {
1595: $items[$n]['latitude'] = (float)$element->y;
1596: $items[$n]['longitude'] = (float)$element->x;
1597: $items[$n]['prefecture'] = (string)$element->prefecture;
1598: $items[$n]['city'] = (string)$element->city;
1599: $items[$n]['city_kana'] = (string)$element->{'city-kana'};
1600: $items[$n]['town'] = (string)$element->town;
1601: $items[$n]['town_kana'] = (string)$element->{'town-kana'};
1602: $items[$n]['postal'] = (string)$element->postal;
1603: $items[$n]['address'] = (string)$element->prefecture . (string)$element->city . (string)$element->town;
1604: $n++;
1605: }
1606: }
1607:
1608: return ($n - 1);
1609: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $items に格納しておく。
「OSM Nominatim Search API」による緯度・経度変換
なお、2024年(令和6年)9月現在、 User-Agent 文字列の一部にメールアドレスを含めることを求めている。"pahooGeoCode.php" の冒頭に定義している変数 $NOMINATIM_EMAIL にご利用のメールアドレスを代入してほしい。
| 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
pahooGeoCode.php
1802: /**
1803: * 指定した検索キーワードの緯度・経度を求める.
1804: * クラウドサービスとしてOSM Nominatim Search API住所検索APIを利用する.
1805: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1806: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1807: * @param string $query 検索キーワード:住所のみ(UTF-8)
1808: * @param array $items 情報を格納する配列
1809: * @return int ヒットした地点数/(-1):API呼び出し失敗
1810: */
1811: function getPointsNominatim_all($query, &$items) {
1812: // リクエストURL
1813: $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . urlencode($query);
1814: $this->webapi = $url;
1815: $n = 1;
1816:
1817: // User-Agent偽装
1818: $header = array(
1819: 'Content-Type: application/x-www-form-urlencoded',
1820: 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ' . $this->NOMINATIM_EMAIL,
1821: );
1822: $stream = stream_context_create(array(
1823: 'http' => array(
1824: 'method' => 'GET',
1825: 'header' => implode("\r\n", $header),
1826: 'ignore_errors'=>TRUE
1827: )
1828: ));
1829: $json = file_get_contents($url, FALSE, $stream);
1830:
1831: // レスポンス・チェック
1832: if ($json == FALSE) {
1833: $this->error = TRUE;
1834: $this->errmsg = '';
1835: $n = 0;
1836: } else {
1837: if ($this->isphp7over()) {
1838: $res = @json_decode($json, FALSE, 512, JSON_BIGINT_AS_STRING);
1839: } else {
1840: $res = @json_decode($json, FALSE, 512);
1841: }
1842: // エラー・チェック
1843: if ($res == FALSE) {
1844: $this->error = TRUE;
1845: $this->errmsg = $res;
1846: return (-1);
1847: }
1848: foreach ($res as $element) {
1849: $items[$n]['latitude'] = (float)$element->lat;
1850: $items[$n]['longitude'] = (float)$element->lon;
1851: $items[$n]['address'] = (string)$element->display_name;
1852: $n++;
1853: }
1854: }
1855: if ($n == 1) {
1856: $this->error = TRUE;
1857: $this->errmsg = 'Not found';
1858: }
1859:
1860: return ($n - 1);
1861: }
クラウドサービスの呼び出し時、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
pahooGeoCode.php
1864: /**
1865: * 指定した検索キーワードの緯度・経度を求める.
1866: * クラウドサービスとして国土地理院ジオコーディングAPIを利用する.
1867: * 検索方式は$matchingにセットする(省略時は'like').
1868: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1869: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1870: * @param string $query 検索キーワード:住所のみ(UTF-8)
1871: * @param array $items 情報を格納する配列
1872: * @return int ヒットした地点数/(-1):API呼び出し失敗
1873: */
1874: function getPointsGSI($query, &$items) {
1875: // リクエストURL
1876: $url = "https://msearch.gsi.go.jp/address-search/AddressSearch?q=" . urlencode($query);
1877: $this->webapi = $url;
1878: $n = 1;
1879:
1880: $this->unknown_certificate();
1881: $json = file_get_contents($url);
1882: // レスポンス・チェック
1883: if ($json == FALSE) {
1884: $this->error = TRUE;
1885: $this->errmsg = '国土地理院ジオコーディングAPIが応答しません';
1886: $n = 0;
1887: } else {
1888: $arr = json_decode($json);
1889: if (count($arr) == 0) {
1890: $this->error = TRUE;
1891: $this->errmsg = '住所が見つかりません';
1892: $n = 0;
1893: } else {
1894: foreach ($arr as $element) {
1895: $items[$n]['latitude'] = (float)$element->geometry->coordinates[1];
1896: $items[$n]['longitude'] = (float)$element->geometry->coordinates[0];
1897: $items[$n]['address'] = (string)$element->properties->title;
1898: $items[$n]['postal'] = (string)$element->properties->addressCode;
1899: $n++;
1900: }
1901: }
1902: }
1903:
1904: return ($n - 1);
1905: }
解説:検索と結果取得
pahooGeoCode.php
2325: /**
2326: * 指定した検索キーワードの緯度・経度を求める.
2327: * クラウドサービスとしてGoogle Geocoding API, Yahoo!ジオコーダAPI,
2328: * HeartRails Geo API, OSM Nominatim Search API,
2329: * 国土地理院ジオコーディングAPIを指定できる.
2330: * Yahoo!ジオコーダAPIを利用する場合は,検索対象カテゴリ$categoryをセットする.
2331: * (省略時は 'like')
2332: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
2333: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
2334: *
2335: * @param string $query 検索キーワード(UTF-8)
2336: * @param int $api 0:Google Geocoding API(省略時)
2337: * 1:Yahoo!ジオコーダAPI
2338: * 11:HeartRails Geo API
2339: * 12:OSM Nominatim Search API
2340: * 13:国土地理院ジオコーディングAPI
2341: * @param string $category 検索対象カテゴリ(YOLPのみ必要)
2342: * address = 住所(省略時)
2343: * landmark = ランドマーク
2344: * world = 世界
2345: * @return array(int ヒットした地点数,string WebAPI)
2346: */
2347: function searchPoint3($query, $api=0, $category='address') {
2348: static $pat1 = '/E(\d+\.?\d*)N(\d+\.?\d*)/i';
2349: static $pat2 = '/E(\d+)\.(\d+)\.(\d+)\.(\d+)N(\d+)\.(\d+)\.(\d+)\.(\d+)/i';
2350:
2351: unset($this->items);
2352: $this->items = array();
2353: $this->hits = 0;
2354:
2355: // 緯度・経度表記(1)
2356: if (preg_match($pat1, $query) > 0) {
2357: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2358: $this->parse_geo($query);
2359: $this->items[1]['address'] = '';
2360: $this->hits = 1;
2361:
2362: // 緯度・経度表記(2)
2363: } else if (preg_match($pat2, $query) > 0) {
2364: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2365: $this->parse_geo($query);
2366: $this->items[1]['address'] = '';
2367: $this->hits = 1;
2368:
2369: // Google Geocoding API使用
2370: } else if ($api == 0) {
2371: $n = $this->getPointsV3_all($query, $this->items);
2372: if ($n == (-1)) { // v.5.73修正
2373: $this->error = TRUE;
2374: $this->errmsg = 'Google Geocoding APIにトラブル発生';
2375: $this->hits = 0;
2376: } else if ($n == 0) {
2377: $this->error = TRUE;
2378: $this->errmsg = '指定キーワードでは検索できない';
2379: $this->hits = 0;
2380: } else {
2381: $this->hits = $n;
2382: }
2383:
2384: // Yahoo!ジオコーダAPI使用
2385: } else if ($api == 1) {
2386: $n = $this->getPointsYOLP_all($query, $this->items, $category);
2387: if ($n == (-1)) { // v.5.73修正
2388: $this->error = TRUE;
2389: $this->errmsg = 'Yahoo!ジオコーダAPIにトラブル発生';
2390: $this->hits = 0;
2391: } else if ($n == 0) {
2392: $this->error = TRUE;
2393: $this->errmsg = '指定キーワードでは検索できない';
2394: $this->hits = 0;
2395: } else {
2396: $this->hits = $n;
2397: }
2398:
2399: // HeartRails Geo API使用
2400: } else if ($api == 11) {
2401: $n = $this->getPointsHeartRailsGeo_all($query, $this->items, 'like');
2402: if ($n == (-1)) { // v.5.73修正
2403: $this->hits = 0;
2404: } else if ($n == 0) {
2405: $this->errmsg = '指定キーワードでは検索できない';
2406: $this->hits = 0;
2407: } else {
2408: $this->hits = $n;
2409: }
2410:
2411: // OSM Nominatim Search API使用
2412: } else if ($api == 12) {
2413: $n = $this->getPointsNominatim_all($query, $this->items);
2414: if ($n == (-1)) {
2415: $this->errmsg = 'OSM Nominatim Search APIにトラブル発生';
2416: $this->hits = 0;
2417: } else if ($n == 0) {
2418: $this->errmsg = '指定キーワードでは検索できない';
2419: $this->hits = 0;
2420: } else {
2421: $this->hits = $n;
2422: }
2423:
2424: // 国土地理院ジオコーディングAPIs使用
2425: } else if ($api == 13) {
2426: $n = $this->getPointsGSI($query, $this->items);
2427: if ($n > 0) {
2428: $this->hits = $n;
2429: }
2430:
2431: // エラー
2432: } else {
2433: $this->error = TRUE;
2434: $this->errmsg = 'ジオコーダーAPIの指定間違い';
2435: $this->hits = 0;
2436: }
2437:
2438: return array($this->hits, $this->webapi);
2439: }
結果はプロパティ $items に格納する。戻り値としてヒットした件数を返す。
pahooGeoCode.php
367: /**
368: * 検索結果(緯度・経度)を取得
369: * @param int $id 取得したい地点番号
370: * @return array(緯度,経度,住所):世界測地系
371: */
372: function getPoint($id) {
373: if ($id <= 0 || $id > $this->hits) {
374: $this->error = TRUE;
375: $this->errmsg = '不正な地点番号';
376: $latitude = FALSE;
377: $longitude = FALSE;
378: $address = FALSE;
379: } else {
380: $this->error = FALSE;
381: $this->errmsg = '';
382: $latitude = $this->items[$id]['latitude'];
383: $longitude = $this->items[$id]['longitude'];
384: $address = $this->items[$id]['address'];
385: }
386:
387: return array($latitude, $longitude, $address);
388: }
解説:小数を指定した桁数で丸める
pahooInputData.php
602: /**
603: * 小数を指定した桁数で丸めて文字列として返す。
604: * 与えた小数の有効桁数より指定桁数が多いときには,末尾に0をサプレスする.
605: * @参考URL https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
606: * @param float $x 丸めたい小数
607: * @param int $dp 小数点以下の桁数(0:整数,負数:丸めない)
608: * @return string 丸めた結果
609: */
610: function roundFloat($x, $dp) {
611: // 丸めない
612: if ($dp < 0) {
613: $y = sprintf('%f', $x);
614: // 整数に丸める
615: } else if ($dp == 0) {
616: $y = sprintf('%d', $x);
617: // 指定した桁数に丸める
618: } else {
619: $ft = '%.' . (int)$dp . 'f';
620: $y = sprintf($ft, $x);
621: }
622: return (string)$y;
623: }
組み込み関数 sprintf を利用し、小数を指定した桁数で丸めて文字列として返す。与えた小数の有効桁数より指定桁数が多いときには、末尾に0をサプレスする。
解説:メインプログラム
address2geo.php
68: // 初期値
69: define('DEF_QUERY', '東京都千代田区丸の内一丁目'); // 検索キー
70: define('DEF_CATEGORY', 'address'); // カテゴリ
71:
72: // 表示幅(ピクセル)
73: define('WIDTH', 600);
74:
75: // 緯度・経度の小数点以下表示桁数(0:整数に丸める,負数:丸めない)
76: define('DISPLAY_DECIMAL_POINT', 6);
77:
78: // 検索キーの最小文字長
79: define('QUERY_MIN_LEN', 3);
80:
81: // 検索キーの最大文字長
82: define('QUERY_MAX_LEN', 99);
83:
84: // 各種定数(END) ===============================================================
85:
86: // 住所・緯度・経度に関わるクラス:include_pathに配置すること
87: require_once('pahooGeoCode.php');
質疑応答
国土地理院のジオコーディングはお試しになっていたと思いますが、なぜ利用されて居なかったのでしょうか? 精度でしょうか?(ヨッシーXX様,2023年6月30日)【回答】
有用な情報をありがとうございます。試していませんでした。近いうちに試してみて、プログラムから利用できるようにしようと思います。
【質問】
PHPで住所・ランドマークから緯度・経度を求めるにおいて、プログラムを実行するとエラーとなっていました。【回答】
ダウンロードしたものもエラーを吐いて実行できませんでした(私の設定ミスでしたら申し訳ありません。) (2024年8月30日)
デフォルトで使用している OSM Nominatim Search API でメールアドレスを知らせないとAPIエラーが出ることが分かりました。これに合わせてプログラムを改良しました。"pahooGeoCode.php" の冒頭に定義している変数 $NOMINATIM_EMAIL にご利用のメールアドレスを代入してください。
また、大量APIコールで OSM Nominatim Search API に負荷をかけてはいけないので、本ページからサンプル・プログラムの実行を省きました。

これらサービスのうち Google は全世界を対象として最も精度の高い検索が可能だが、有料サービスに移行したため(無料枠あり)、その他の無料利用できるサービスを選択できるようにしている。
ぱふぅ家のホームページで紹介するプログラムの住所検索機能は、すべてこのクラス pahooGeoCode を流用している。
(2025年12月6日)PHP8.5対応:double→float表記変更
(2025年8月24日).pahooEnv 導入
(2025年6月14日)GoogleMaps JavaScript APIの変更に対応した.
(2024年9月14日)pahooGeoCode->$NOMINATIM_EMAIL追加, searchPoint3()のエラー対策追加