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

サンプル・プログラム
stationCongestion.php | サンプル・プログラム本体。 |
pahooGeoCode.php | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooCalendar.php | 暦・潮位計算クラス pahooCalendar。 暦・潮位計算クラスの使い方は「PHPで二十四節気・七十二候一覧を作成」「PHPで月齢を計算」「PHPで日出没・月出没・月齢・潮を計算」「PHPで潮位を計算する」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
1.0.0 | 2024/05/11 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
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 |
6.3.0 | 2023/07/02 | getPointsGSI()追加 |
6.2.0 | 2023/07/02 | ip2address()追加 |
バージョン | 更新日 | 内容 |
---|---|---|
4.5.0 | 2024/03/17 | ヒジュラ暦メソッドを追加 |
4.4.1 | 2024/03/17 | getCabinetOfficeHolidayTable() -- bug-fix |
4.4.0 | 2024/02/25 | 内閣府の祝日表を参照できるようにした |
4.3.2 | 2023/02/11 | getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅 |
4.3.1 | 2023/02/03 | 表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン,七十二候 |
バージョン | 更新日 | 内容 |
---|---|---|
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
1.4.2 | 2024/01/28 | exitIfLessVersion() メッセージ修正 |
1.4.1 | 2023/09/30 | コメントの訂正 |
1.4.0 | 2023/09/09 | $_GET, $_POST参照をfilter_input()関数に置換 |
1.3.0 | 2023/07/11 | roundFloat() 追加 |
サンプル・プログラムの流れ(メイン)

準備: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 = '*****************************';
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

地図や住所検索として Google を利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。
準備:地図サービスの選択
70: //地図描画サービスの選択
71: // 0:Google
72: // 2:地理院地図・OSM
73: define('MAPSERVICE', 0);
74:
75: //住所検索サービスの選択
76: // 0:Google
77: // 1:Yahoo!ジオコーダAPI
78: // 11:HeartRails Geo API
79: // 12:OSM Nominatim Search API
80: // 13:国土地理院ジオコーディングAPI
81: define('GEOSERVICE', 0);
82:
83: //逆ジオコーディングサービスの選択
84: // 0:Google
85: // 1:Yahoo!JAPAN
86: // 11:HeartRails Geo API
87: // 21:簡易ジオコーディングサービス
88: define('REVGEOSERVICE', 1);
住所検索サービスは、Google、Yahoo!JAPAN、HeartRails Geo APIから選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、Google、Yahoo!JAPAN、HeartRails Geo API、簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
RapidAPI NAVITIME API
APIキーと利用機能をHTTPヘッダで渡し、各種パラメータをGET渡しすることで、JSON形式の応答を得ることができる。
利用にはRapidAPIのAPIキー(無償)が必要で、その入手方法は「RapidAPI - 各種WebAPIの登録方法」を参照されたい。
NAVITIME APIの一覧と利用料金は https://api-sdk.navitime.co.jp/api/specs/description/about_navitime_api.html をご覧いただきたい。月間500アクセスまでは無料で利用できる。
422: class pahooRapidNAVITIME {
423:
424: //RapidAPIキー
425: //取得方法 https://www.paho.org/e-soul/webtech/php06/php06-01-02.shtm#RapidAPI
426: const rapidApiKey = '**********************************************';
解説:最寄駅検索
URL | |
---|---|
https://navitime-transport.p.rapidapi.com/transport_node/around | |
HTTPヘッダ名 | 値 |
X-RapidAPI-Host | navitime-transport.p.rapidapi.com |
X-RapidAPI-Key | APIキー |
フィールド名 | 要否 | 内 容 |
---|---|---|
coord | 必須 | 最寄駅を取得したい緯度,経度(カンマ区切り) |
type | 省略可能 | 交通機関タイプ:station 鉄道駅,airport 空港,port 港,busstop 路線バスのバス停(要契約), shuttle_busstop 空港連絡バスのバス停, highway_busstop 高速バスのバス停(要契約) |
limit | 省略可能 | 応答の上限件数【デフォルト 10/最大 30】 |
term | 省略可能 | 応答待ち時間(秒)【デフォルト 60/最大 1440】 |
datum | 省略可能 | 測地系(wgs84またはtokyo)【デフォルト wgs84】 |
walk_speed | 省略可能 | 歩行速度(km/h)【デフォルト 5/最小 3/最大 8】 |
447: /**
448: * 最寄駅検索 - RapidAPI NAVITIME API 2.0
449: * @param double $latitude 緯度(世界測地系)
450: * @param double $longitude 経度(世界測地系)
451: * @param array $items 応答情報を格納する配列
452: * @return array(ヒットした施設数, メッセージ, APIのURL)
453: */
454: function getResultsTransportNodeAround($latitude, $longitude, &$items) {
455: //クラウドサービスの呼び出し
456: $curl = curl_init();
457: $url = 'https://navitime-transport.p.rapidapi.com/transport_node/around?coord=' . $latitude . ',' . $longitude . '&options=by_link';
458: curl_setopt($curl, CURLOPT_URL , $url);
459: curl_setopt($curl, CURLOPT_HEADER, 1) ;
460: curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
461: curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); //結果を文字列で
462: curl_setopt($curl, CURLOPT_ENCODING, '');
463: curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
464: curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
465: curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
466: curl_setopt($curl, CURLOPT_TIMEOUT, 30);
467: curl_setopt($curl, CURLOPT_HTTPHEADER, [
468: 'X-RapidAPI-Host: navitime-transport.p.rapidapi.com',
469: 'X-RapidAPI-Key: ' . self::rapidApiKey
470: ]);
471:
472: $res1 = @curl_exec($curl);
473: $res2 = @curl_getinfo($curl);
474: $errmsg = curl_error($curl);
475:
476: if ($res1 == FALSE) {
477: return array(0, $errmsg, $url);
478: }
479:
480: //JSONデータを配列に格納する
481: $json = substr($res1, $res2['header_size']);
482: $results = json_decode($json);
483:
484: //応答のデータ構造チェック
485: if (! isset($results->items)) {
486: $errmsg = '検索に失敗しました';
487: return array(0, $errmsg, $url);
488: }
489:
490: //応答を配列へ代入する.
491: $cnt = 1;
492: foreach ($results->items as $node) {
493: //記号(A, B, C...)
494: $items[$cnt]['id'] = (string)$this->num2alpha($cnt);
495: //駅/バス停のノードID
496: $items[$cnt]['nodeId'] = (string)$node->id;
497: //駅/バス停の読み仮名
498: $items[$cnt]['ruby'] = (string)$node->ruby;
499: //住所の表示名
500: $items[$cnt]['address_name'] = (string)$node->address_name;
501: //住所コード
502: $items[$cnt]['address_code'] = (string)$node->address_code;
503: //緯度
504: $items[$cnt]['latitude'] = (float)$node->coord->lat;
505: //経度
506: $items[$cnt]['longitude'] = (float)$node->coord->lon;
507: //検索地点からの距離(メートル)
508: $items[$cnt]['distance'] = (int)$node->distance;
509: //検索地点からの所要時間(分)
510: $items[$cnt]['time'] = (int)$node->time;
511: //路線ID
512: $items[$cnt]['linkId'] = (string)$node->link->id;
513: //路線名称
514: $items[$cnt]['linkName'] = (string)$node->link->name;
515: //駅名の抽出(nameに路線名が混在しているので)
516: $arr = array();
517: $name = (string)$node->name;
518: if (preg_match('/\s.*?([^\s]*)$/ui', $name, $arr) > 0) {
519: $name = isset($arr[1]) ? $arr[1] : $name;
520: }
521: if (preg_match('/^([^\(]+)/ui', $name, $arr) > 0) {
522: $name = isset($arr[1]) ? $arr[1] : $name;
523: }
524: $items[$cnt]['title'] = $name;
525: //情報ウィンドウに表示する内容(HTML文)
526: $distance = number_format($items[$cnt]['distance']);
527: $items[$cnt]['description'] =<<< EOT
528: {$items[$cnt]['title']} [{$items[$cnt]['linkName']}] {$distance}m
529: EOT;
530: $cnt++;
531: }
532: return array($cnt - 1, $errmsg, $url);
533: }
応答データには、JSON形式データの前にヘッダ情報が混じっているので、 substr 関数を使ってJSON形式データのみを抽出してから、 json_decode 関数を使ってデコードし、配列 $items に格納する。
解説:混雑度予想
URL | |
---|---|
https://navitime-congestion-prediction.p.rapidapi.com/congestion_prediction/node | |
HTTPヘッダ名 | 値 |
X-RapidAPI-Host | navitime-congestion-prediction.p.rapidapi.com |
X-RapidAPI-Key | APIキー |
フィールド名 | 要否 | 内 容 |
---|---|---|
id | 必須 | 駅/バス停のノードID(最寄駅検索で取得したID) |
date | 必須 | 日付(yyyy-mm-dd形式;本日を含む未来日であること) |
535: /**
536: * 指定した駅の混雑度予想 - RapidAPI NAVITIME API 2.0
537: * @param string $id 駅/バス停のノードID
538: * @param string $date 予想したい年月日(例:2024-05-06;未来日であること)
539: * @param array $items 応答情報を格納する配列
540: * @return array(エラーメッセージ, APIのURL)
541: */
542: function getResultsCongestionNode($id, $date, &$items) {
543: //クラウドサービスの呼び出し
544: $curl = curl_init();
545: $url = 'https://navitime-congestion-prediction.p.rapidapi.com/congestion_prediction/node?id=' . $id . '&date=' . $date;
546: curl_setopt($curl, CURLOPT_URL , $url);
547: curl_setopt($curl, CURLOPT_HEADER, 1) ;
548: curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
549: curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); //結果を文字列で
550: curl_setopt($curl, CURLOPT_ENCODING, '');
551: curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
552: curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
553: curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
554: curl_setopt($curl, CURLOPT_TIMEOUT, 30);
555: curl_setopt($curl, CURLOPT_HTTPHEADER, [
556: 'X-RapidAPI-Host: navitime-congestion-prediction.p.rapidapi.com',
557: 'X-RapidAPI-Key: ' . self::rapidApiKey
558: ]);
559:
560: $res1 = @curl_exec($curl);
561: $res2 = @curl_getinfo($curl);
562: $errmsg = curl_error($curl);
563:
564: if ($res1 == FALSE) {
565: return array(0, $errmsg, $url);
566: }
567:
568: //JSONデータを配列に格納する
569: $json = substr($res1, $res2['header_size']);
570: $results = json_decode($json);
571:
572: //応答のデータ構造チェック
573: if (! isset($results->items)) {
574: $errmsg = '検索に失敗しました';
575: return array(0, $errmsg, $url);
576: }
577:
578: //応答を配列へ代入する.
579: $cnt = 1;
580: foreach ($results->items[0]->congestions as $node) {
581: $dt = $node->time;
582: if (preg_match('/T([0-9]+)\:/i', (string)$node->time, $arr) > 0) {
583: $hour = (int)($arr[1]);
584: if ($hour <= 2) {
585: $hour += 24;
586: }
587: $items[$hour] = (float)($node->prediction_rate);
588: }
589: $cnt++;
590: }
591: return array($cnt - 1, $errmsg, $url);
592: }
応答データには、JSON形式データの前にヘッダ情報が混じっているので、 substr 関数を使ってJSON形式データのみを抽出してから、 json_decode 関数を使ってデコードし、配列 $items に格納する。
669: <td style="text-align:center;">{$val['id']}</td>
670: <td><div class="station" onClick="getResultscongestionNode('{$val['nodeId']}')">{$val['title']}</div></td>
671: <td>{$val['linkName']}</td>
672: <td style="text-align:right;">{$distance}</td>
162: <script>
163: /**
164: * 駅名をクリックしたら,nodeIdを代入し,submitする→混雑度予想処理に入る.
165: * @param string idNode 駅/バス停のノードID
166: * @return なし
167: */
168: function getResultscongestionNode(idNode) {
169: document.getElementById('nodeId').value = idNode;
170: myform.submit();
171: }
172: </script>
まず初めに最寄駅検索を行い、そこで得られたノードID($val['nodeId'])を、一覧表の駅名をクリックするとJavaScript関数 getResultscongestionNode を呼び出すようにする。
JavaScript関数 getResultscongestionNode では、受け取ったノードIDをDOMオブジェクト nodeId(実体はhidden属性をもったテキストボックス)に格納し、submitすることで、このページを再読み込みしたことを同じ動きになる。
706: $json = json_encode($items);
707: $html =<<< EOT
708: <body>
709: {$jsmap}
710: <h2>{$title} {$version}</h2>
711: <form name="myform" method="post" action="{$myself}" enctype="multipart/form-data">
712: 検索キー <input type="text" name="query" size="30" value="{$spot['query']}">
713: <input type="submit" id="exec" name="exec" value="キーワード検索">
714: <input type="submit" id="map" name="map" value="地図検索">
715: <input type="submit" id="clear" name="clear" value="リセット">
716: {$str_radio}<br>
717: 年月日 <input class="datepicker" type="text" id="yyyymmdd" name="yyyymmdd" size="10" value="{$date}" >
718:
719: <input type="hidden" id="latitude" name="latitude" value="{$spot['latitude']}" >
720: <input type="hidden" id="longitude" name="longitude" value="{$spot['longitude']}" >
721: <input type="hidden" id="zoom" name="zoom" value="{$spot['zoom']}" >
722: <input type="hidden" id="type" name="type" value="{$spot['type']}" >
723: <input type="hidden" id="nodeId" name="nodeId" value="">
724: <input type="hidden" id="mode" name="mode" value="{$mode}">
725: <textarea style="display:none" id="json" name="json">{$json}</textarea>
その他の使用クラウド連携、JavaScriptライブラリなど
日付をカレンダーから入力するJavaScriptライブラリ jQuery UI:Datepicker の使い方は、「PHPで日付入力:カレンダーから選択(WebAPI版)」をご覧いただきたい。
棒グラフ描画に使ったJavaScriptライブラリ jqPlot の使い方は、「PHPでNHK政治意識月例調査をグラフ表示」をご覧いただきたい。
参考サイト
- RapidAPI NAVITIME API
- RapidAPI - 各種WebAPIの登録方法:ぱふぅ家のホームページ
- PHPで住所・ランドマークから緯度・経度を求める:ぱふぅ家のホームページ
- PHPで緯度・経度から住所を求める:ぱふぅ家のホームページ
- PHPで住所・ランドマークから最寄り駅を求める
- PHPで日付入力:カレンダーから選択(WebAPI版):ぱふぅ家のホームページ
- PHPでNHK政治意識月例調査をグラフ表示:ぱふぅ家のホームページ