PHPで住所・ランドマークから最寄り駅を求める

(1/1)
HeartRails Geo API」は、路線/駅名データ等の地理情報を無償の WebAPI として提供している。
これと、Google や地理院地図、オープンストリートマップの地図サービスをマッシュアップすることで、住所やランドマークから最寄り駅を求める PHP プログラムを作ってみることにする。
なお、Yahoo! JavaScript マップは、2020 年(令和 2 年)10 月 31 日をもってサービスを終了しており利用できない。

(2021 年 2 月 20 日)PHP8 対応,Yahoo! JavaScript マップ廃止
(2020 年 3 月 21 日)OSM Nominatim Search API を利用できるようにした。
(2019 年 5 月 8 日)地理院地図、OpenStreetMap も利用できるようにした。
(2019 年 3 月 16 日)Yahoo! JavaScript マップも利用できるようにした。

目次

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

PHPで住所・ランドマークから最寄り駅を求める
Googleマップ表示

サンプル・プログラム

圧縮ファイルの内容
stationsearch.phpサンプル・プログラム本体。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。
サンプル・プログラムは 2 つの機能を持つ。
1 つは、そのまま実行すると、検索キーワードを入力する画面を表示する機能――[検索]ボタンを押下することで、検索結果を表示する。
もう 1 つは、前述の変数を GET 渡しで呼び出すことで、検索結果のみを表示する機能である。たとえば「東京都千代田区皇居外苑1-1」の最寄り駅を検索する場合は、URL で 'stationsearch.php?query=%93%8C%8B%9E%93s%90%E7%91%E3%93c%8B%E6%8Dc%8B%8F%8AO%89%91%82P%81%7C%82P' と指定してやればよい。

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

PHPで住所・ランドマークから最寄り駅を求める

準備:pahooGeoCode クラス

0037: class pahooGeoCode {
0038:     var $items;      //検索結果格納用
0039:     var $error;      //エラーフラグ
0040:     var $hits;       //検索ヒット件数
0041:     var $webapi; //直前に呼び出したWebAPI URL
0042: 
0043:     //Google Cloud Platform APIキー
0044:     //https://cloud.google.com/maps-platform/
0045:     //※Google Maps APIを利用しないのなら登録不要
0046:     var $GOOGLE_API_KEY_1 = '**************************';   //HTTPリファラ用
0047:     var $GOOGLE_API_KEY_2 = '**************************';   //IP制限用
0048: 
0049:     //Yahoo! JAPAN Webサービス アプリケーションID
0050:     //https://e.developer.yahoo.co.jp/register
0051:     //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
0052:     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が必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPI の登録方法」を、それぞれ参照されたい。

準備:地図サービスの選択

0037: //地図描画サービスの選択
0038: //    0:Google
0039: //    2:地理院地図・OSM
0040: define('MAPSERVICE', 0);
0041: 
0042: //住所検索サービスの選択
0043: //    0:Google
0044: //    1:Yahoo!JAPAN
0045: //   11:HeartRails Geo API
0046: //   12:OSM Nominatim Search API
0047: define('GEOSERVICE', 1);
0048: 
0049: //逆ジオコーディングサービスの選択
0050: //    0:Google
0051: //    1:Yahoo!JAPAN
0052: //   11:HeartRails Geo API
0053: //   21:簡易ジオコーディングサービス
0054: define('REVGEOSERVICE', 0);

表示する地図は、Google マップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。
住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIから選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
PHPで住所・ランドマークから最寄り駅を求める
地理院地図(淡色)
PHPで住所・ランドマークから最寄り駅を求める
OpenStreetMap

HeartRails Geo API 最寄駅検索

HeartRails Geo API」は、2015 年(平成 27 年)9 月現在、以下の API を無償公開している。
これらの API は、入力パラメータ(IN)は GET 渡しで、出力結果(OUT)は XML で戻るという形である。
  • エリア情報取得 API
  • 都道府県情報取得 API
  • 市区町村情報取得 API
  • 町域情報取得 API
  • 最寄駅情報取得 API
  • 郵便番号による住所検索 API
  • 緯度経度による住所検索 API
  • キーワードによる住所検索 API
  • 「エリア名」 「市区町村名」 「町域名」 の連結コンボボックス
  • 「都道府県名」 「市区町村名」 「町域名」 の連結コンボボックス
  • 「郵便番号」 による住所検索フォーム
WebAPIのURL
URL
http://express.heartrails.com/api/xml

入力パラメータ
フィールド名 要否 内  容
method 必須 メソッド名:getStation(固定)
x 必須 最寄り駅を取得したい場所の経度(世界測地系)。
y 必須 最寄り駅を取得したい場所の緯度(世界測地系)。
応答データ(xml) response station name 駅名 line 路線名 distance 検索地点からの距離 x 経度 y 緯度 prefecture 都道府県 postal 郵便番号 next 次の駅 prev 前の駅

解説:HeartRails Geo APIの呼び出し

0237: /**
0238:  * HeartRails Express のURLを取得する
0239:  * @param double $lat 緯度(世界測地系)
0240:  * @param double $lng 経度(世界測地系)
0241:  * @return string URL
0242: */
0243: function getURL_Heartrails($lat$lng) {
0244:     $res = "http://express.heartrails.com/api/xml?method=getStations&x={$lng}&y={$lat}";
0245: 
0246:     return $res;
0247: }

0249: /**
0250:  * HeartRails Express API から必要な情報を配列に格納する
0251:  * @param double $latitude  緯度(世界測地系)
0252:  * @param double $longitude 経度(世界測地系)
0253:  * @return array(ヒットした施設数, メッセージ, APIのURL)
0254:  * @return int ヒット数
0255: */
0256: function getResults_Heartrails($latitude$longitude, &$items) {
0257: //受信データの要素名
0258: $tbl = array(
0259:     'name',            //最寄駅名
0260:     'prev',            //前の駅名 (始発駅の場合は null
0261:     'next',            //次の駅名 (終着駅の場合は null
0262:     'x',            //最寄駅の経度 (世界測地系)
0263:     'y',            //最寄駅の緯度 (世界測地系)
0264:     'distance',    //指定の場所から最寄駅までの距離 (精度は 10 m)
0265:     'postal',        //最寄駅の郵便番号 
0266:     'prefecture',    //最寄駅の存在する都道府県名
0267:     'line'         //最寄駅の存在する路線名
0268: );
0269: 
0270:     $url = $this->getURL_Heartrails($latitude$longitude);   //リクエストURL
0271:     $cnt = 1;
0272: 
0273: //PHP4用; DOM XML利用
0274:     if (! isphp5over()) {
0275:         if (($dom = $this->read_xml($url)) == NULL) {
0276:             return array(FALSE, 'WebAPIのトラブルです.', FALSE);
0277:         }
0278:         $resultset = $dom->get_elements_by_tagname('response');
0279:         $results = $resultset[0]->get_elements_by_tagname('station');
0280:         //検索結果取りだし
0281:         foreach ($results as $element) {
0282:             foreach ($tbl as $name) {
0283:                 $node = $element->get_elements_by_tagname($name);
0284:                 if ($node != NULL) {
0285:                     $items[$cnt][$name] = (string)$node[0]->get_content();
0286:                 }
0287:             }
0288:             $items[$cnt]['id']        = $this->num2alpha($cnt);
0289:             $items[$cnt]['title']     = $items[$cnt]['name'];
0290:             $items[$cnt]['longitude'] = $items[$cnt]['x'];
0291:             $items[$cnt]['latitude']  = $items[$cnt]['y'];
0292: $items[$cnt]['description'] =<<< EOD
0293: {$items[$cnt]['name']}&nbsp;({$items[$cnt]['line']}){$items[$cnt]['distance']}
0294: EOD;
0295:             $cnt++;
0296:         }
0297: 
0298: //PHP5用; SimpleXML利用
0299:     } else {
0300:         $response = simplexml_load_file($url);
0301:         //レスポンス・チェック
0302:         if (isset($response->station) == FALSE) {
0303:             return array(FALSE, 'WebAPIのトラブルです.', FALSE);
0304:         }
0305:         //検索結果取りだし
0306:         foreach ($response->station as $element) {
0307:             foreach ($tbl as $name) {
0308:                 if (isset($element->$name)) {
0309:                     $items[$cnt][$name] = (string)$element->$name;
0310:                 }
0311:             }
0312:             $items[$cnt]['id']        = $this->num2alpha($cnt);
0313:             $items[$cnt]['title']     = $items[$cnt]['name'];
0314:             $items[$cnt]['longitude'] = $items[$cnt]['x'];
0315:             $items[$cnt]['latitude']  = $items[$cnt]['y'];
0316: $items[$cnt]['description'] =<<< EOD
0317: {$items[$cnt]['name']}&nbsp;({$items[$cnt]['line']}){$items[$cnt]['distance']}
0318: EOD;
0319:             $cnt++;
0320:         }
0321:     }
0322: 
0323:     return array($cnt - 1, '', $url);
0324: }

HeartRails Geo 最寄駅情報取得 APIの使い方は、前回と同じである。応答メッセージの処理は、PHP4 では DOM XML を、PHP5 以降では SimpleXML を使っている。

Googleマップ描画

Google Maps JavaScript API は、JavaScript を使って Google マップを動的に描画するための WebAPI である。

0853: /**
0854:  * Googleマップを描く
0855:  * @param string $id        マップID
0856:  * @param float $latitude  中心座標:緯度(世界測地系)
0857:  * @param float $longitude 中心座標:経度(世界測地系)
0858:  * @param string $type      マップタイプ:HYBRID/ROADMAP/SATELLITE/TERRAIN
0859:  * @param int    $zoom      拡大率
0860:  * @param string $call      イベント発生時にコールする関数(省略可)
0861:  * @param array  $items     地点情報(省略可能)
0862:  *                  string title       タイトル
0863:  *                  string description 情報ウィンドウに表示する内容(HTML文)
0864:  *                  float latitude    緯度
0865:  *                  float longitude   経度
0866:  *                  string icon        アイコンURL
0867:  * @param string $call2     追加スクリプト(省略可)
0868:  * @return string Googleマップのコード
0869: */
0870: function drawGMap($id$latitude$longitude$type$zoom$call=NULL$items=NULL$call2=NULL) {
0871:     $key = $this->GOOGLE_API_KEY_1;
0872:     $call = ($call != NULL) ? $call . '()' : '';
0873: $code =<<< EOD
0874: <script src="https://maps.googleapis.com/maps/api/js?key={$key}&amp;callback=initMap&amp;region=JP" async defer></script>
0875: <script>
0876: function initMap() {
0877:     var map = new google.maps.Map(document.getElementById('{$id}'), {
0878:         center: new google.maps.LatLng({$latitude}, {$longitude}),
0879:         zoom: {$zoom},
0880:         mapTypeId: google.maps.MapTypeId.{$type},
0881:         mapTypeControl: true,
0882:         scaleControl: true
0883:     });
0884: 
0885:     map.addListener('dragend', getPointData);
0886:     map.addListener('zoom_changed', getPointData);
0887:     map.addListener('maptypeid_changed', getPointData);
0888: 
0889:     //イベント発生時の地図情報を取得・格納
0890:     function getPointData() {
0891:         var point = map.getCenter();
0892:         //経度
0893:         if (document.getElementById("longitude") != null) {
0894:             document.getElementById("longitude").value = point.lng();
0895:         }
0896:         //緯度
0897:         if (document.getElementById("latitude") != null) {
0898:             document.getElementById("latitude").value = point.lat();
0899:         }
0900:         //ズーム
0901:         if (document.getElementById("zoom") != null) {
0902:             document.getElementById("zoom").value = map.getZoom();
0903:         }
0904:         //地図タイプ
0905:         if (document.getElementById("type") != null) {
0906:             var type_g = map.getMapTypeId();
0907:             var types = {"roadmap":"地図", "satellite":"航空写真", "hybrid":"ハイブリッド", "terrain":"地形図" };
0908:             for (key in types) {
0909:                 if (key == type_g) {
0910:                     document.getElementById("type").value = key;
0911:                     break;
0912:                 }
0913:             }
0914:         }
0915:         {$call}
0916:     }
0917: 
0918: EOD;
0919:     //地点情報
0920:     if ($items != NULL) {
0921:         foreach ($items as $i=>$item) {
0922:             if ($i > 26)    break;       //'Z'を超えたらスキップ
0923:             //アイコン
0924:             $mark = $this->num2alpha($i);
0925:             $icon = isset($item['icon']) ? $item['icon'] : 
0926:                         "http://www.google.com/mapfiles/marker{$mark}.png";
0927:             list($icon_width$icon_height) = getimagesize($icon);
0928: $code .=<<< EOD
0929: var icon_{$mark} = {
0930:     url: '{$icon}',
0931:     size: new google.maps.Size({$icon_width}, {$icon_height}),
0932:     origin: new google.maps.Point(0, 0),
0933:     anchor: new google.maps.Point({$icon_width} / 2, {$icon_height})
0934: };
0935: var marker_{$mark} = new google.maps.Marker({
0936:     position: new google.maps.LatLng({$item['latitude']}, {$item['longitude']}),
0937:     map: map,
0938:     icon: icon_{$mark},
0939:     title: '{$item['title']}',
0940:     zIndex: 100
0941: });
0942: 
0943: EOD;
0944:             if (isset($item['description'])) {
0945: $code .=<<< EOD
0946: var infowindow_{$mark} = new google.maps.InfoWindow({
0947:     content: '{$item['description']}',
0948:     maxWidth: 200
0949: });
0950: marker_{$mark}.addListener('click', function() {
0951:     infowindow_{$mark}.open(map, marker_{$mark});
0952: });
0953: 
0954: EOD;
0955:             }
0956:         }
0957:     }
0958:     //追加関数
0959:     if ($call2 != NULL) {
0960: $code .=<<< EOD
0961: {$call2}
0962: 
0963: EOD;
0964:     }
0965: $code .=<<< EOD
0966: }
0967: </script>
0968: 
0969: EOD;
0970: 
0971:     return $code;
0972: }

メソッド drawGMap は、Google マップを描画するための JavaScript を生成する。
まずソースとして、"https://maps.googleapis.com/maps/api/js" を読み込む。このとき、パラメータ keyGoogle Cloud Platform API キー を渡してやる必要がある。
また、コールバック関数として initMap() を呼び出し、このユーザー関数内で初期化を行う。

マップのドラッグ、ズーム変更、マップタイプ変更のイベントを拾って(addListner)、getPointDate() 関数を呼び出す。
このユーザー関数内で、緯度・経度、ズーム値、マップタイプを、ID で示されるオブジェクトに格納する。hidden 属性のテキストボックスに格納することを想定している。
これにより、ページ切替が起きても地図の状態を保持できる。
また、本メソッドに JavaScript を引数 $call として渡してやれば、getPointDate() 関数内で追加で呼び出す。

引数 $items を渡してやれば、地図上にマーキングする。
$items は 2 次元配列で、1 次元目は地点番号(1 以上)、2 次元目は情報の種類である。たとえば $items[3]['description'] には、地点番号 3 の情報ウィンドウに表示する内容 HTML を代入する。
$items には、マッピングするアイコン URL も指定可能である。指定しない場合は、Google マップの標準的なアルファベットアイコンによってマーキングする。

地理院地図・OSM描画

国土地理院 は、基本測量結果や電子国土基本図、白地図、航空写真などを、各縮尺に応じて、256×256 ドットの分割画像である地理院タイルとして、URL を指定して直接参照できるようにしている。

ここでは、このタイル画像を繋げて、Google マップのようなユーザー・インターフェースを提供する無償の JavaScript ライブラリ Leaflet を利用することにする。

あわせて、自由に利用できる世界地図作成プロジェクト「OpenStreetMap」(OSM)が提供する地図タイルも利用できるようにした。

1686: /**
1687:  * Leafletによるマップ描画
1688:  * @param string $id        マップID
1689:  * @param float  $latitude  中心座標:緯度(世界測地系)
1690:  * @param float  $longitude 中心座標:経度(世界測地系)
1691:  * @param string $type      マップタイプ:GSISTD/GSIPALE/GSIBLANK/GSIPHOTO/OSM
1692:  * @param int    $zoom      拡大率
1693:  * @param string $call      イベント発生時にコールする関数(省略可)
1694:  * @param array  $items     地点情報(省略可能)
1695:  *                  string description 情報ウィンドウに表示する内容(HTML文)
1696:  *                  float  latitude    緯度
1697:  *                  float  longitude   経度
1698:  *                  string icon        アイコンURL
1699:  * @param string $call2     追加スクリプト(省略可)
1700:  * @return string Leafletマップのコード
1701: */
1702: function drawLeaflet($id$latitude$longitude$type$zoom$call=NULL$items=NULL$call2=NULL) {
1703: 
1704: $code =<<< EOD
1705: <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
1706: <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
1707: <script>
1708: window.onload = function() {
1709:     var map = L.map('{$id}',{zoomControl:false});
1710:     map.setView([{$latitude}, {$longitude}], {$zoom});
1711:     L.control.scale({
1712:         maxWidth: 200,
1713:         position: 'bottomright',
1714:         imperial: false
1715:     }).addTo(map);
1716:     L.control.zoom({position:'topleft'}).addTo(map);
1717: 
1718:     //地理院地図:標準地図
1719:     var GSISTD = new L.tileLayer(
1720:         'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
1721:         {
1722:             attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
1723:             minZoom: 0,
1724:             maxZoom: 18,
1725:             name: 'GSISTD'
1726:         });
1727:     //地理院地図:淡色地図
1728:     var GSIPALE = new L.tileLayer(
1729:         'https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
1730:         {
1731:             attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
1732:             minZoom: 2,
1733:             maxZoom: 18,
1734:             name: 'GSIPALE'
1735:         });
1736:     //地理院地図:白地図
1737:     var GSIBLANK = new L.tileLayer(
1738:         'https://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png',
1739:         {
1740:             attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
1741:             minZoom: 5,
1742:             maxZoom: 14,
1743:             name: 'GSIBLANK'
1744:         });
1745:     //地理院地図:写真
1746:     var GSIPHOTO = new L.tileLayer(
1747:         'https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg',
1748:         {
1749:             attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
1750:             minZoom: 2,
1751:             maxZoom: 18,
1752:             name: 'GSIPHOTO'
1753:         });
1754:     //OpenStreetMap
1755:     var OSM = new L.tileLayer(
1756:         'https://tile.openstreetmap.jp/{z}/{x}/{y}.png',
1757:         {
1758:             attribution: "© <a href='https://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors",
1759:             minZoom: 0,
1760:             maxZoom: 18,
1761:             name: 'OSM'
1762:         });
1763: 
1764:     //baseMapsオブジェクトにタイル設定
1765:     var baseMaps = {
1766:         "地理院地図" : GSISTD,
1767:         "淡色地図" : GSIPALE,
1768:         "白地図" : GSIBLANK,
1769:         "写真地図" : GSIPHOTO,
1770:         "オープンストリートマップ" : OSM
1771:     };
1772: 
1773:     //layersコントロールにbaseMapsオブジェクトを設定して地図に追加
1774:     L.control.layers(baseMaps).addTo(map);
1775:     {$type}.addTo(map);
1776: 
1777:     //イベント追加
1778:     map.on('moveend', getPointData);
1779:     map.on('zoomend', getPointData);
1780:     map.on('baselayerchange', getPointData);
1781: 
1782:     //イベント発生時の地図情報を取得・格納
1783:     function getPointData() {
1784:         var pos = map.getCenter();
1785:         //経度
1786:         if (document.getElementById('longitude') != null) {
1787:             document.getElementById('longitude').value = pos.lng;
1788:         }
1789:         //緯度
1790:         if (document.getElementById('latitude') != null) {
1791:             document.getElementById('latitude').value = pos.lat;
1792:         }
1793:         //ズーム
1794:         if (document.getElementById('zoom') != null) {
1795:             document.getElementById('zoom').value = map.getZoom();
1796:         }
1797:         //タイプ
1798:         if (document.getElementById('type') != null) {
1799:             for (var k in baseMaps) {
1800:                 if (map.hasLayer(baseMaps[k])) {
1801:                     document.getElementById('type').value = baseMaps[k].options.name;
1802:                 }
1803:             }
1804:         }
1805:         {$call}
1806:     }
1807: 
1808: 
1809: EOD;
1810:     //地点情報
1811:     if ($items != NULL) {
1812:         foreach ($items as $i=>$item) {
1813:             if ($i > 26)    break;       //'Z'を超えたらスキップ
1814:             //アイコン
1815:             $mark = $this->num2alpha($i);
1816:             $icon = isset($item['icon']) ? $item['icon'] : 
1817:                         "http://www.google.com/mapfiles/marker{$mark}.png";
1818:             list($icon_width$icon_height) = getimagesize($icon);
1819:             $offx = round($icon_width / 2);
1820:             $offy = $icon_height;
1821:             $info  = isset($item['description']) ? "marker_{$mark}.bindPopup('{$item['description']}', {maxWidth: 200});" : '';
1822: 
1823: $code .=<<< EOD
1824:     var icon_{$mark} = new L.icon({
1825:         iconUrl: '{$icon}',
1826:         iconAnchor: [{$offx}, {$offy}]
1827:     });
1828:     var marker_{$mark} = new L.Marker([{$item['latitude']}, {$item['longitude']}], {icon: icon_{$mark}}).addTo(map);
1829:     {$info}
1830: 
1831: EOD;
1832:         }
1833:     }
1834:     //追加関数
1835:     if ($call2 != NULL) {
1836: $code .=<<< EOD
1837: {$call2}
1838: 
1839: EOD;
1840:     }
1841: $code .=<<< EOD
1842: }
1843: </script>
1844: 
1845: EOD;
1846: 
1847:     return $code;
1848: }

メソッド drawLeaflet は、地理院地図と OSM を描画するための JavaScript を生成する。
まずソースとして、UNPKG から Leaflet 本体とスタイルシートを読み込む。

Leaflet のレイヤを切り替えることで、以下の地図が切り替わるようにしてある。
  1. 地理院地図:標準地図
  2. 地理院地図:淡色地図
  3. 地理院地図:白地図
  4. 地理院地図:写真
  5. OpenStreetMap
この他、タイル形式の地図コンテンツがあれば、自由に追加できる。じつは Google マップもタイル形式で呼び出すことができるのだが、API コールしないと Google の規約違反となるため、実装してはいけない。

マップのドラッグ、ズーム変更、レイヤ変更のイベントを拾って(on)、getPointDate() 関数を呼び出す。
このユーザー関数内で、緯度・経度、ズーム値を、ID で示されるオブジェクトに格納する。hidden 属性のテキストボックスに格納することを想定している。
これにより、ページ切替が起きても地図の状態を保持できる。
また、本メソッドに JavaScript を引数 $call として渡してやれば、getPointDate() 関数内で追加で呼び出す。

引数 $items を渡してやれば、地図上にマーキングする。
$items は 2 次元配列で、1 次元目は地点番号(1 以上)、2 次元目は情報の種類である。たとえば $items[3]['description'] には、地点番号 3 の情報ウィンドウに表示する内容 HTML を代入する。
$items には、マッピングするアイコン URL も指定可能である。指定しない場合は、Google マップの標準的なアルファベットアイコンによってマーキングする。

動的マップ描画

2153: /**
2154:  * 地図サービスを利用してJavaScriptマップを描く
2155:  *
2156:  * @param string $id        マップID
2157:  * @param float  $latitude  中心座標:緯度(世界測地系)
2158:  * @param float  $longitude 中心座標:経度(世界測地系)
2159:  * @param string $type      マップタイプ
2160:  *                              Googleの場合 HYBRID/ROADMAP/SATELLITE/TERRAIN
2161:  *                              Yahoo!JAPANの場合 NORMAL/PHOTO/B1/OSM
2162:  * @param int    $zoom      拡大率
2163:  * @param string $call      イベント発生時にコールする関数(省略可)
2164:  * @param array  $items     地点情報(省略可能)
2165:  *                  string title       タイトル(Yahoo!では無効)
2166:  *                  string description 情報ウィンドウに表示する内容(HTML文)
2167:  *                  float latitude    緯度
2168:  *                  float longitude   経度
2169:  *                  string icon        アイコンURL
2170:  * @param string $api   0:Google Maps JavaScript(省略時)
2171:  *                        1:Yahoo! JavaScriptマップ
2172:  *                        2:地理院地図・OSM(Leaflet使用)
2173:  * @param string $call2 追加スクリプト(省略可)
2174:  * @return string JavaScriptマップのコード
2175: */
2176: function drawJSmap($id$latitude$longitude$type$zoom$call=NULL$items=NULL$api=0, $call2=NULL) {
2177:     //マップタイプの読み替え
2178:     static $tbl1 = array('HYBRID'=>'PHOTO', 'ROADMAP'=>'NORMAL', 'SATELLITE'=>'PHOTO', 'TERRAIN'=>'PHOTO');
2179:     static $tbl2 = array('NORMAL'=>'ROADMAP', 'PHOTO'=>'SATELLITE', 'B1'=>'ROADMAP', 'OSM'=>'ROADMAP');
2180:     static $tbl3 = array('HYBRID'=>'gsistd', 'ROADMAP'=>'OSM', 'SATELLITE'=>'GSIPHOTO', 'TERRAIN'=>'GSIPHOTO');
2181:     $type = strtoupper($type);
2182: 
2183:     switch ($api) {
2184:     //Google Maps JavaScript
2185:     case 0;
2186:         $type = isset($tbl2[$type]) ? $tbl2[$type] : $type;
2187:         $js = $this->drawGMap($id$latitude$longitude$type$zoom$call$items$call2);
2188:         break;
2189:     //Yahoo! JavaScriptマップ
2190:     case 1:
2191:         $type = isset($tbl1[$type]) ? $tbl1[$type] : $type;
2192:         $js = $this->drawYOLPmap($id$latitude$longitude$type$zoom$call$items$call2);
2193:         break;
2194:     //地理院地図・OSM(Leaflet使用)
2195:     case 2:
2196:         $type = isset($tbl3[$type]) ? $tbl3[$type] : $type;
2197:         $js = $this->drawLeaflet($id$latitude$longitude$type$zoom$call$items$call2);
2198:         break;
2199:     }
2200: 
2201:     return $js;
2202: }

メソッド drawJSmap は、引数 $api の値によって、Google マップ描画メソッド drawGMap、地理院地図・ OSM 描画メソッド drawLeaflet のいずれかを呼び出す。
マップタイプについては、相互に読み替えができるようにしてある。

その他の WebAPI

pahooGeoCode::searchPoint3 が呼び出す WebAPI については、「PHP で住所・ランドマークから緯度・経度を求める」を参照のこと。
pahooGeoCode::getAddress3 が呼び出す WebAPI については、「PHP で緯度・経度から住所を求める」を参照のこと。

活用例

みんなの知識 ちょっと便利帳」では、「グーグルマップで見る京都の地下鉄路線図」からリンクする「地図・住所から「最寄り駅」をグーグルマップで探す - 初期設定:京都府庁周辺」や、「地図・住所から「最寄り駅」をグーグルマップで探す」で本プログラムを利用し、検索しやすいページを提供している。ありがとうございます。

参考サイト

(この項おわり)
header