目次
- サンプル・プログラムの実行例
- サンプル・プログラム
- サンプル・プログラムの流れ
- 準備: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.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化 |
5.2 | 2020/03/21 | OSM Nominatim Search API追加 |
バージョン | 更新日 | 内容 |
---|---|---|
6.5.0 | 2025/06/14 | GoogleMaps JavaScript APIの変更に対応 |
6.4.0 | 2025/03/01 | makeYOLP_GeoSelectCategory()--引数$flagWorld追加 |
6.3.3 | 2024/09/14 | $this->NOMINATIM_EMAIL 追加 |
6.3.2 | 2024/02/14 | getStaticMap() -- bug-fix |
6.3.1 | 2023/07/09 | bug-fix |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.1 | 2025/03/15 | validRegexPattern() -- debug |
1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
1.7.0 | 2024/10/09 | validURL() validEmail() 追加 |
1.6.0 | 2024/10/07 | isButton() -- buttonタグに対応 |
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
サンプル・プログラムの流れ

準備:pahooGeoCode クラス
pahooGeoCode.php
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: var $GOOGLE_MAP_ID = '*************************'; // GoogleMaps ID
50:
51: // Yahoo! JAPAN Webサービス アプリケーションID
52: // https://e.developer.yahoo.co.jp/register
53: // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
54: var $YAHOO_APPLICATION_ID = '*****************************';
55:
56: // OSM Nominatim Search API利用時に知らせるメールアドレス
57: // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
58: var $NOMINATIM_EMAIL = '*****************************';
59:
60: // ジオどすII APIキー【廃止】
61: // http://geodosu.com/user/register
62: var $APIKEY_GEOTOS = '*****************';
63:
64: // IP2Location.io APIキー
65: // https://www.ip2location.io/
66: // ※IP2Location.ioを利用しないのなら登録不要
67: var $IP2LOCATION_API_KEY = '*****************';
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

地図や住所検索として Google を利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。
準備:住所検索サービスの選択
address2geo.php
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', 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
190: /**
191: * 指定した検索キーワードからGoogleMaps API Geocoding(V3) のURLを取得する.
192: * @param string $query 検索キーワード(UTF-8)
193: * @return string URL URL
194: */
195: function getURL_GeoCodeAPI_V3($query) {
196: $key = $this->GOOGLE_API_KEY_2;
197: return "https://maps.googleapis.com/maps/api/geocode/xml?key={$key}&language=ja®ion=JP&address=" . urlencode($query);
198: }
pahooGeoCode.php
200: /**
201: * 指定した検索キーワードの緯度・経度を求める.
202: * クラウドサービスとしてGoogle Geocoding API(V3) を利用する.
203: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
204: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
205: * @param string $query 検索キーワード
206: * @param array $items 情報を格納する配列
207: * @return int ヒットした施設数/(-1):API呼び出し失敗
208: */
209: function getPointsV3_all($query, &$items) {
210: $url = $this->getURL_GeoCodeAPI_V3($query); // リクエストURL
211: $this->webapi = $url;
212: $n = 1;
213:
214: // PEAR::XML_Unserializer
215: if (class_exists('XML_Unserializer')) {
216: $xml = new XML_Unserializer();
217: $xml_data = file_get_contents($url);
218: $xml->unserialize($xml_data);
219: $arr = $xml->getUnserializedData();
220: // レスポンス・チェック
221: if (preg_match('/ok/i', $arr['status']) == 0) return (-1);
222: // 位置情報
223: if (isset($arr['result']['geometry'])) {
224: $items[$n]['latitude'] = $arr['result']['geometry']['location']['lat'];
225: $items[$n]['longitude'] = $arr['result']['geometry']['location']['lng'];
226: $items[$n]['address'] = $this->trimAddress($arr['result']['formatted_address']);
227: $n++;
228: } else {
229: foreach ($arr['result'] as $val) {
230: $items[$n]['latitude'] = $val['geometry']['location']['lat'];
231: $items[$n]['longitude'] = $val['geometry']['location']['lng'];
232: $items[$n]['address'] = $this->trimAddress($val['formatted_address']);
233: $n++;
234: }
235: }
236: $xml = NULL;
237:
238: // PHP4用; DOM XML利用
239: } else if ($this->isphp5over() == FALSE) {
240: if (($dom = $this->read_xml($url)) == NULL) return FALSE;
241: $gr = $dom->get_elements_by_tagname('GeocodeResponse');
242: // レスポンス・チェック
243: $res = $gr[0]->get_elements_by_tagname('status');
244: if (preg_match("/ok/i", $res[0]->get_content()) == 0) return 0;
245: // 位置情報
246: $res = $gr[0]->get_elements_by_tagname('result');
247: foreach ($res as $val) {
248: $geo = $val->get_elements_by_tagname('geometry');
249: $loc = $geo[0]->get_elements_by_tagname('location');
250: $lat = $loc[0]->get_elements_by_tagname('lat');
251: $items[$n]['latitude'] = (double)$lat[0]->get_content();
252: $lng = $loc[0]->get_elements_by_tagname('lng');
253: $items[$n]['longitude'] = (double)$lng[0]->get_content();
254: $addr = $val->get_elements_by_tagname('formatted_address');
255: $items[$n]['address'] = $this->trimAddress((string)$addr[0]->get_content());
256: $n++;
257: }
258: // PHP5用; SimpleXML利用
259: } else {
260: $this->unknown_certificate();
261: $res = simplexml_load_file($url);
262: // レスポンス・チェック
263: if (preg_match("/ok/i", $res->status) == 0) return 0;
264: foreach ($res->result as $element) {
265: $items[$n]['latitude'] = (double)$element->geometry->location->lat;
266: $items[$n]['longitude'] = (double)$element->geometry->location->lng;
267: $items[$n]['address'] = $this->trimAddress((string)$element->formatted_address);
268: $n++;
269: }
270: }
271: return ($n - 1);
272: }
検索結果が複数ある場合に備え、緯度・経度・人間が読める住所のセットを、連想配列のプロパティ $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
1266: /**
1267: * 指定した検索キーワードからYOLPコンテンツジオコーダAPIのURLを取得する.
1268: * @param string $query 検索キーワード(UTF-8)
1269: * @param string $category 検索対象カテゴリ
1270: * address = 住所(省略時)
1271: * landmark = ランドマーク
1272: * world = 世界
1273: * @return string URL リクエストURL
1274: */
1275: function getURL_YOLP_GeoCoder($query, $category='address') {
1276: $appid = $this->YAHOO_APPLICATION_ID;
1277: return "https://map.yahooapis.jp/geocode/cont/V1/contentsGeoCoder?appid={$appid}&el=UTF-8&output=xml&category={$category}&query=" . urlencode($query);
1278: }
pahooGeoCode.php
1280: /**
1281: * 指定した検索キーワードの緯度・経度を求める.
1282: * クラウドサービスとしてYOLPコンテンツジオコーダAPIを利用する.
1283: * $categoryに検索対象カテゴリをセットする(省略時は'address').
1284: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1285: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1286: * @param string $query 検索キーワード
1287: * @param array $items 情報を格納する配列
1288: * @param string $category 検索対象カテゴリ
1289: * address = 住所(省略時)
1290: * landmark = ランドマーク
1291: * world = 世界
1292: * @return int ヒットした施設数/(-1):API呼び出し失敗
1293: */
1294: function getPointsYOLP_all($query, &$items, $category='address') {
1295: $url = $this->getURL_YOLP_GeoCoder($query, $category); // リクエストURL
1296: $this->webapi = $url;
1297: $n = 1;
1298:
1299: $this->unknown_certificate();
1300: $res = simplexml_load_file($url);
1301: // レスポンス・チェック
1302: if (!isset($res->ResultInfo)) return (-1);
1303: if (isset($res->ResultInfo->Total) && ((int)$res->ResultInfo->Total <= 0)) return 0; // v.5.73追加
1304:
1305: foreach ($res->Feature as $element) {
1306: if (preg_match('/([\-0-9\.]+)\,([\-0-9\.]+)/i', $element->Geometry->Coordinates, $arr) > 0) {
1307: if (isset($arr[1]) && isset($arr[2])) {
1308: $items[$n]['latitude'] = (double)$arr[2];
1309: $items[$n]['longitude'] = (double)$arr[1];
1310: $items[$n]['address'] = (string)$element->Property->Address;
1311: $n++;
1312: }
1313: }
1314: }
1315:
1316: return ($n - 1);
1317: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $items に格納しておく。
pahooGeoCode.php
1319: /**
1320: * YOLPコンテンツジオコーダAPI のカテゴリ選択ラジオボタンの生成
1321: * @param string $name HTML name
1322: * @param string $default デフォルト値(省略時は空文字)
1323: * @param string $flagWorld 世界を選択できるようにする(省略時はTRUE)
1324: * @return string HTML
1325: */
1326: function makeYOLP_GeoSelectCategory($name, $default='', $flagWorld=TRUE) {
1327: // デフォルト値設定
1328: if (isset($this->YOLP_GeoCategory[$default])) {
1329: foreach ($this->YOLP_GeoCategory as $key=>$item) {
1330: $item[$key]['checked'] = '';
1331: }
1332: $this->YOLP_GeoCategory[$default]['checked'] = 'checked';
1333: }
1334: // 選択ラジオボタンの生成
1335: $html = '';
1336: $i = 1;
1337: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1338: if (! $flagWorld && ($key == 'world')) continue;
1339: $html .= "<input type=\"radio\" name=\"{$name}\" value=\"{$key}\" {$val['checked']} />{$val['title']} ";
1340: $i++;
1341: }
1342: return $html;
1343: }
pahooGeoCode.php
1353: /**
1354: * checkedされているカテゴリを検索する
1355: * @return string 選択された関数名/FALSE=checkedされている処理がない
1356: */
1357: function getYOLP_GeoSelectCategory() {
1358: foreach ($this->YOLP_GeoCategory as $key=>$val) {
1359: if ($val['checked'] == 'checked') return $key;
1360: }
1361:
1362: return FALSE;
1363: }
pahooGeoCode.php
1365: /**
1366: * カテゴリをchekedする
1367: * @param string $val カテゴリ値
1368: * @return bool TRUE/FALSE
1369: */
1370: function setYOLP_GeoSelectCategory($val) {
1371: $old = $this->getYOLP_GeoSelectCategory();
1372: if ($val != FALSE) $this->YOLP_GeoCategory[$old]['checked'] = '';
1373: $this->YOLP_GeoCategory[$val]['checked'] = 'checked';
1374:
1375: return TRUE;
1376: }
「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
1512: /**
1513: * 指定した検索キーワードの緯度・経度を求める.
1514: * クラウドサービスとしてHeartRails Geo APIの住所検索APIを利用する.
1515: * 検索方式は$matchingにセットする(省略時は'like').
1516: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1517: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1518: * @param string $query 検索キーワード:住所のみ(UTF-8)
1519: * @param array $items 情報を格納する配列
1520: * @param string $matching 検索方式
1521: * prefix = 前方一致
1522: * like = 部分一致(省略時)
1523: * suffix = 後方一致
1524: * @return int ヒットした地点数/(-1):API呼び出し失敗
1525: */
1526: function getPointsHeartRailsGeo_all($query, &$items, $matching='like') {
1527: // リクエストURL
1528: $url = "https://geoapi.heartrails.com/api/xml?method=suggest&matching={$matching}&keyword=" . urlencode($query);
1529: $this->webapi = $url;
1530: $n = 1;
1531:
1532: $this->unknown_certificate();
1533: $res = simplexml_load_file($url);
1534: // レスポンス・チェック
1535: if (isset($res->error)) {
1536: $this->error = TRUE;
1537: $this->errmsg = (string)$res->error;
1538: $n = 0;
1539: } else if (! isset($res->location)) {
1540: $this->error = TRUE;
1541: $this->errmsg = 'Not found';
1542: $n = 1;
1543: } else {
1544: foreach ($res->location as $element) {
1545: $items[$n]['latitude'] = (double)$element->y;
1546: $items[$n]['longitude'] = (double)$element->x;
1547: $items[$n]['prefecture'] = (string)$element->prefecture;
1548: $items[$n]['city'] = (string)$element->city;
1549: $items[$n]['city_kana'] = (string)$element->{'city-kana'};
1550: $items[$n]['town'] = (string)$element->town;
1551: $items[$n]['town_kana'] = (string)$element->{'town-kana'};
1552: $items[$n]['postal'] = (string)$element->postal;
1553: $items[$n]['address'] = (string)$element->prefecture . (string)$element->city . (string)$element->town;
1554: $n++;
1555: }
1556: }
1557:
1558: return ($n - 1);
1559: }
検索結果が複数ある場合に備え、緯度・経度・住所のセットを、連想配列のプロパティ $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
1752: /**
1753: * 指定した検索キーワードの緯度・経度を求める.
1754: * クラウドサービスとしてOSM Nominatim Search API住所検索APIを利用する.
1755: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1756: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1757: * @param string $query 検索キーワード:住所のみ(UTF-8)
1758: * @param array $items 情報を格納する配列
1759: * @return int ヒットした地点数/(-1):API呼び出し失敗
1760: */
1761: function getPointsNominatim_all($query, &$items) {
1762: // リクエストURL
1763: $url = 'https://nominatim.openstreetmap.org/search?format=json&q=' . urlencode($query);
1764: $this->webapi = $url;
1765: $n = 1;
1766:
1767: // User-Agent偽装
1768: $header = array(
1769: 'Content-Type: application/x-www-form-urlencoded',
1770: '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,
1771: );
1772: $stream = stream_context_create(array(
1773: 'http' => array(
1774: 'method' => 'GET',
1775: 'header' => implode("\r\n", $header),
1776: 'ignore_errors'=>TRUE
1777: )
1778: ));
1779: $json = file_get_contents($url, FALSE, $stream);
1780:
1781: // レスポンス・チェック
1782: if ($json == FALSE) {
1783: $this->error = TRUE;
1784: $this->errmsg = '';
1785: $n = 0;
1786: } else {
1787: if ($this->isphp7over()) {
1788: $res = @json_decode($json, FALSE, 512, JSON_BIGINT_AS_STRING);
1789: } else {
1790: $res = @json_decode($json, FALSE, 512);
1791: }
1792: // エラー・チェック
1793: if ($res == FALSE) {
1794: $this->error = TRUE;
1795: $this->errmsg = $res;
1796: return (-1);
1797: }
1798: foreach ($res as $element) {
1799: $items[$n]['latitude'] = (double)$element->lat;
1800: $items[$n]['longitude'] = (double)$element->lon;
1801: $items[$n]['address'] = (string)$element->display_name;
1802: $n++;
1803: }
1804: }
1805: if ($n == 1) {
1806: $this->error = TRUE;
1807: $this->errmsg = 'Not found';
1808: }
1809:
1810: return ($n - 1);
1811: }
クラウドサービスの呼び出し時、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
1814: /**
1815: * 指定した検索キーワードの緯度・経度を求める.
1816: * クラウドサービスとして国土地理院ジオコーディングAPIを利用する.
1817: * 検索方式は$matchingにセットする(省略時は'like').
1818: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
1819: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
1820: * @param string $query 検索キーワード:住所のみ(UTF-8)
1821: * @param array $items 情報を格納する配列
1822: * @return int ヒットした地点数/(-1):API呼び出し失敗
1823: */
1824: function getPointsGSI($query, &$items) {
1825: // リクエストURL
1826: $url = "https://msearch.gsi.go.jp/address-search/AddressSearch?q=" . urlencode($query);
1827: $this->webapi = $url;
1828: $n = 1;
1829:
1830: $this->unknown_certificate();
1831: $json = file_get_contents($url);
1832: // レスポンス・チェック
1833: if ($json == FALSE) {
1834: $this->error = TRUE;
1835: $this->errmsg = '国土地理院ジオコーディングAPIが応答しません';
1836: $n = 0;
1837: } else {
1838: $arr = json_decode($json);
1839: if (count($arr) == 0) {
1840: $this->error = TRUE;
1841: $this->errmsg = '住所が見つかりません';
1842: $n = 0;
1843: } else {
1844: foreach ($arr as $element) {
1845: $items[$n]['latitude'] = (double)$element->geometry->coordinates[1];
1846: $items[$n]['longitude'] = (double)$element->geometry->coordinates[0];
1847: $items[$n]['address'] = (string)$element->properties->title;
1848: $items[$n]['postal'] = (string)$element->properties->addressCode;
1849: $n++;
1850: }
1851: }
1852: }
1853:
1854: return ($n - 1);
1855: }
解説:検索と結果取得
pahooGeoCode.php
2222: /**
2223: * 指定した検索キーワードの緯度・経度を求める.
2224: * クラウドサービスとしてGoogle Geocoding API, Yahoo!ジオコーダAPI,
2225: * HeartRails Geo API, OSM Nominatim Search API,
2226: * 国土地理院ジオコーディングAPIを指定できる.
2227: * Yahoo!ジオコーダAPIを利用する場合は,検索対象カテゴリ$categoryをセットする.
2228: * (省略時は 'like')
2229: * 検索結果結果は複数になることがあり,配列$itemsに格納する.
2230: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
2231: *
2232: * @param string $query 検索キーワード(UTF-8)
2233: * @param int $api 0:Google Geocoding API(省略時)
2234: * 1:Yahoo!ジオコーダAPI
2235: * 11:HeartRails Geo API
2236: * 12:OSM Nominatim Search API
2237: * 13:国土地理院ジオコーディングAPI
2238: * @param string $category 検索対象カテゴリ(YOLPのみ必要)
2239: * address = 住所(省略時)
2240: * landmark = ランドマーク
2241: * world = 世界
2242: * @return array(int ヒットした地点数,string WebAPI)
2243: */
2244: function searchPoint3($query, $api=0, $category='address') {
2245: static $pat1 = '/E(\d+\.?\d*)N(\d+\.?\d*)/i';
2246: static $pat2 = '/E(\d+)\.(\d+)\.(\d+)\.(\d+)N(\d+)\.(\d+)\.(\d+)\.(\d+)/i';
2247:
2248: unset($this->items);
2249: $this->items = array();
2250: $this->hits = 0;
2251:
2252: // 緯度・経度表記(1)
2253: if (preg_match($pat1, $query) > 0) {
2254: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2255: $this->parse_geo($query);
2256: $this->items[1]['address'] = '';
2257: $this->hits = 1;
2258:
2259: // 緯度・経度表記(2)
2260: } else if (preg_match($pat2, $query) > 0) {
2261: list($this->items[1]['latitude'], $this->items[1]['longitude']) =
2262: $this->parse_geo($query);
2263: $this->items[1]['address'] = '';
2264: $this->hits = 1;
2265:
2266: // Google Geocoding API使用
2267: } else if ($api == 0) {
2268: $n = $this->getPointsV3_all($query, $this->items);
2269: if ($n == (-1)) { // v.5.73修正
2270: $this->error = TRUE;
2271: $this->errmsg = 'Google Geocoding APIにトラブル発生';
2272: $this->hits = 0;
2273: } else if ($n == 0) {
2274: $this->error = TRUE;
2275: $this->errmsg = '指定キーワードでは検索できない';
2276: $this->hits = 0;
2277: } else {
2278: $this->hits = $n;
2279: }
2280:
2281: // Yahoo!ジオコーダAPI使用
2282: } else if ($api == 1) {
2283: $n = $this->getPointsYOLP_all($query, $this->items, $category);
2284: if ($n == (-1)) { // v.5.73修正
2285: $this->error = TRUE;
2286: $this->errmsg = 'Yahoo!ジオコーダAPIにトラブル発生';
2287: $this->hits = 0;
2288: } else if ($n == 0) {
2289: $this->error = TRUE;
2290: $this->errmsg = '指定キーワードでは検索できない';
2291: $this->hits = 0;
2292: } else {
2293: $this->hits = $n;
2294: }
2295:
2296: // HeartRails Geo API使用
2297: } else if ($api == 11) {
2298: $n = $this->getPointsHeartRailsGeo_all($query, $this->items, 'like');
2299: if ($n == (-1)) { // v.5.73修正
2300: $this->hits = 0;
2301: } else if ($n == 0) {
2302: $this->errmsg = '指定キーワードでは検索できない';
2303: $this->hits = 0;
2304: } else {
2305: $this->hits = $n;
2306: }
2307:
2308: // OSM Nominatim Search API使用
2309: } else if ($api == 12) {
2310: $n = $this->getPointsNominatim_all($query, $this->items);
2311: if ($n == (-1)) {
2312: $this->errmsg = 'OSM Nominatim Search APIにトラブル発生';
2313: $this->hits = 0;
2314: } else if ($n == 0) {
2315: $this->errmsg = '指定キーワードでは検索できない';
2316: $this->hits = 0;
2317: } else {
2318: $this->hits = $n;
2319: }
2320:
2321: // 国土地理院ジオコーディングAPIs使用
2322: } else if ($api == 13) {
2323: $n = $this->getPointsGSI($query, $this->items);
2324: if ($n > 0) {
2325: $this->hits = $n;
2326: }
2327:
2328: // エラー
2329: } else {
2330: $this->error = TRUE;
2331: $this->errmsg = 'ジオコーダーAPIの指定間違い';
2332: $this->hits = 0;
2333: }
2334:
2335: return array($this->hits, $this->webapi);
2336: }
結果はプロパティ $items に格納する。戻り値としてヒットした件数を返す。
pahooGeoCode.php
339: /**
340: * 検索結果(緯度・経度)を取得
341: * @param int $id 取得したい地点番号
342: * @return array(緯度,経度,住所):世界測地系
343: */
344: function getPoint($id) {
345: if ($id <= 0 || $id > $this->hits) {
346: $this->error = TRUE;
347: $this->errmsg = '不正な地点番号';
348: $latitude = FALSE;
349: $longitude = FALSE;
350: $address = FALSE;
351: } else {
352: $this->error = FALSE;
353: $this->errmsg = '';
354: $latitude = $this->items[$id]['latitude'];
355: $longitude = $this->items[$id]['longitude'];
356: $address = $this->items[$id]['address'];
357: }
358:
359: return array($latitude, $longitude, $address);
360: }
解説:小数を指定した桁数で丸める
pahooInputData.php
548: /**
549: * 小数を指定した桁数で丸めて文字列として返す。
550: * 与えた小数の有効桁数より指定桁数が多いときには,末尾に0をサプレスする.
551: * @参考URL https://www.pahoo.org/e-soul/webtech/php06/php06-08-01.shtm
552: * @param float $x 丸めたい小数
553: * @param int $dp 小数点以下の桁数(0:整数,負数:丸めない)
554: * @return string 丸めた結果
555: */
556: function roundFloat($x, $dp) {
557: // 丸めない
558: if ($dp < 0) {
559: $y = sprintf('%f', $x);
560: // 整数に丸める
561: } else if ($dp == 0) {
562: $y = sprintf('%d', $x);
563: // 指定した桁数に丸める
564: } else {
565: $ft = '%.' . (int)$dp . 'f';
566: $y = sprintf($ft, $x);
567: }
568: return (string)$y;
569: }
組み込み関数 sprintf を利用し、小数を指定した桁数で丸めて文字列として返す。与えた小数の有効桁数より指定桁数が多いときには、末尾に0をサプレスする。
解説:メインプログラム
address2geo.php
66: //初期値
67: define('DEF_QUERY', '東京都千代田区丸の内一丁目'); //検索キー
68: define('DEF_CATEGORY', 'address'); //カテゴリ
69:
70: //表示幅(ピクセル)
71: define('WIDTH', 600);
72:
73: //緯度・経度の小数点以下表示桁数(0:整数に丸める,負数:丸めない)
74: define('DISPLAY_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日)【回答】
有用な情報をありがとうございます。試していませんでした。近いうちに試してみて、プログラムから利用できるようにしようと思います。

【質問】
PHPで住所・ランドマークから緯度・経度を求めるにおいて、プログラムを実行するとエラーとなっていました。【回答】
ダウンロードしたものもエラーを吐いて実行できませんでした(私の設定ミスでしたら申し訳ありません。) (2024年8月30日)
デフォルトで使用している OSM Nominatim Search API でメールアドレスを知らせないとAPIエラーが出ることが分かりました。これに合わせてプログラムを改良しました。"pahooGeoCode.php" の冒頭に定義している変数 $NOMINATIM_EMAIL にご利用のメールアドレスを代入してください。
また、大量APIコールで OSM Nominatim Search API に負荷をかけてはいけないので、本ページからサンプル・プログラムの実行を省きました。
これらサービスのうち Google は全世界を対象として最も精度の高い検索が可能だが、有料サービスに移行したため(無料枠あり)、その他の無料利用できるサービスを選択できるようにしている。
ぱふぅ家のホームページで紹介するプログラムの住所検索機能は、すべてこのクラス pahooGeoCode を流用している。
(2024年9月14日)pahooGeoCode->$NOMINATIM_EMAIL追加, searchPoint3()のエラー対策追加