目次
サンプル・プログラムの実行例
サンプル・プログラム
| search_hotel.php | サンプル・プログラム本体。 |
| .pahooEnv | クラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。 使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooGeoCode.php | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooRakuten.php | 楽天ウェブサービスに関わるクラス pahooRakuten。 使い方は「PHPで最寄りのネットができるホテルを検索する」などを参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 3.6.4 | 2025/11/29 | PHP8.5対応:curl_closeを実行しないようにした |
| 3.6.3 | 2025/08/14 | searchVacantHotelsURL() 日本測地系にデグレード |
| 3.6.2 | 2023/07/09 | bug-fix |
| 3.6.1 | 2022/12/13 | PHP8.2対応 |
| 3.6 | 2022/02/05 | 楽天商品検索API (version:2017-07-06)に変更 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 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インストール手順
これで準備は完了だ。
準備:pahooInputData 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備: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でクラスを使ってテキストの読みやすさを調べる」を参照されたい。
準備:地図サービス(クラウドサービス)の選択
search_hotel.php
58: // 地図描画サービスの選択
59: // 0:Google
60: // 2:地理院地図・OSM
61: define('MAPSERVICE', 2);
62:
63: // 住所検索サービスの選択
64: // 0:Google
65: // 1:Yahoo!ジオコーダAPI
66: // 11:HeartRails Geo API
67: // 12:OSM Nominatim Search API
68: // 13:国土地理院ジオコーディングAPI
69: define('GEOSERVICE', 11);
70:
71: // 逆ジオコーディングサービスの選択
72: // 0:Google
73: // 1:Yahoo!JAPAN
74: // 11:HeartRails Geo API
75: // 21:簡易ジオコーディングサービス
76: define('REVGEOSERVICE', 11);
住所検索サービスは、Google、HeartRails Geo API、OSM Nominatim Search API から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、Google、Yahoo!JAPAN、HeartRails Geo API、簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
準備:pahooRakuten クラス
pahooRakuten.php
19: // 楽天ウェブサービス・クラス ===============================================
20: class pahooRakuten {
21: public $error; // エラー・フラグ
22: public $errmsg; // エラー・メッセージ
23: public $hits; // 検索ヒット件数
24: public $webapi; // 直前に呼び出したWebAPI URL
25:
26: // 楽天ウェブサービス
27: // https://www.pahoo.org/e-soul/webtech/php06/php06-01-02.shtm#Rakuten 参照
28: public $APPLICATIONID = ''; // アプリID
29: public $APPLICATION_SECRET = ''; // シークレット
30: public $AFFILIATEID = ''; // アフィリエイトID
31:
32: /**
33: * コンストラクタ
34: * @param なし
35: * @return なし
36: */
37: function __construct() {
38: if (isset($_ENV['PAHOO_RAKUTEN_APP_ID'])) {
39: $this->APPLICATIONID = $_ENV['PAHOO_RAKUTEN_APP_ID'];
40: }
41: if (isset($_ENV['PAHOO_RAKUTEN_APP_SECRET'])) {
42: $this->APPLICATION_SECRET = $_ENV['PAHOO_RAKUTEN_APP_SECRET'];
43: }
44: if (isset($_ENV['PAHOO_RAKUTEN_AFFILIATEID'])) {
45: $this->AFFILIATEID = $_ENV['PAHOO_RAKUTEN_AFFILIATEID'];
46: }
47:
48: // プロパティを初期化する.
49: $this->error = FALSE;
50: $this->errmsg = '';
51: $this->hits = 0;
52: $this->webapi = '';
53: }
楽天ウェブサービスには、アプリID や アフィリエイトID が必要で、その入手方法は「楽天ウェブサービス - WebAPIの登録方法」を参照されたい。
PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。
「楽天トラベル施設検索API」による施設情報検索
| URL |
|---|
| https://app.rakuten.co.jp/services/api/Travel/SimpleHotelSearch/20170426 |
| フィールド名 | 要否 | 内 容 |
|---|---|---|
| appid | 必須 | 楽天ウェブサービスのアプリケーションID。 |
| format | 任意 | 'xml'または'json' 【デフォルト】json |
| callback | 任意 | JSONPとして出力する際のコールバック関数名 (UTF-8でURLエンコードした文字列) 英数字、「.(ドット)」、「_(アンダーバー)」、「[(中括弧)」、「](中括弧)」のいずれか1文字以上 |
| elements | 任意 | 出力パラメーター指定:カンマ区切りで、必要な出力パラメータを指定した場合、指定された出力パラメータのみを返却する。 【デフォルト】ALL |
| latitude | 必須 | 緯度:日本測地系、単位は秒、ミリ秒は小数点以下2桁以内で指定すること。 例)128216.17 ただし、datumTypeに1を指定した場合は、世界測地系、単位は度で指定すること。 例)35.6065914 |
| longitude | 必須 | 経度。日本測地系、単位は秒、ミリ秒は小数点以下2桁以内で指定すること。 例)503259.29 ただし、datumTypeに1を指定した場合は、世界測地系、単位は度で指定すること。 例)139.7513225 |
| searchRadius | 任意 | 検索半径:緯度経度検索時の検索半径(単位km) 0.1以上、3.0以下 小数点以下は1桁までであること |
| datumType | 任意 | 緯度経度タイプ:入力及び出力パラメータの緯度経度タイプを指定する。 1:世界測地系、単位は度。 2:日本測地系、単位は秒。 【デフォルト】2 |
| squeezeCondition | 任意 | kinen:禁煙ルーム internet:インターネットが出来る部屋 daiyoku:大浴場あり onsen:温泉 |
解説:クラウドサービスの呼び出し
pahooRakuten.php
90: /**
91: * WebAPIを呼び出して応答データを取得する(https用)
92: * @param string $url リスクエストURL
93: * @return string 応答データ/FALSE=失敗
94: */
95: function callWebAPI($url) {
96: $ch = curl_init($url);
97: curl_setopt($ch, CURLOPT_HEADER, FALSE);
98: curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
99: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // サーバ証明書検証をスキップ
100: curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 〃
101: $result = curl_exec($ch);
102: if (PHP_VERSION_ID < 80500) {
103: curl_close($ch);
104: }
105:
106: return $result;
107: }
解説:ホテル検索
pahooRakuten.php
111: var $RakutenBooksItems = array(
112: 'title', // 書籍タイトル
113: 'titleKana', // 書籍タイトル カナ
114: 'subTitle', // 書籍サブタイトル
115: 'subTitleKana', // 書籍サブタイトル カナ
116: 'seriesName', // 叢書名
117: 'seriesNameKana', // 叢書名カナ
118: 'contents', // 多巻物収録内容
119: 'contentsKana', // 多巻物収録内容カナ
120: 'author', // 著者名
121: 'authorKana', // 著者名カナ
122: 'publisherName', // 出版社名
123: 'size', // 書籍のサイズ
124: 'isbn', // ISBNコード(書籍コード)
125: 'itemCaption', // 商品説明文
126: 'salesDate', // 発売日
127: 'itemPrice', // 税込み販売価格
128: 'listPrice', // 定価
129: 'discountRate', // 割引率
130: 'discountPrice', // 割引価格
131: 'itemUrl', // 商品URL
132: 'affiliateUrl', // アフィリエイトURL
133: 'smallImageUrl', // 商品画像 64x64URL
134: 'mediumImageUrl', // 商品画像 128x128URL
135: 'largeImageUrl', // 商品画像 200x200URL
136: 'chirayomiUrl', // チラよみURL
137: 'availability', // 在庫状況
138: 'postageFlag', // 送料フラグ
139: 'limitedFlag', // 限定フラグ
140: 'reviewCount', // レビュー件数
141: 'reviewAverage', // レビュー平均
142: 'booksGenreId' // 楽天ブックスジャンルID
143: );
pahooRakuten.php
436: /**
437: * 楽天トラベル施設検索API のURLを取得する
438: * @param float $latitude 緯度(世界測地系)
439: * @param float $longitude 経度(世界測地系)
440: * @param int $searchRadius 検索半径,単位km
441: * @param array $squeezeConditions 絞込み条件の配列
442: * @return string URL 楽天トラベル施設検索API のURL
443: */
444: function searchHotelsURL($latitude, $longitude, $searchRadius, $squeezeConditions) {
445: $appid = $this->APPLICATIONID;
446: $affid = $this->AFFILIATEID;
447:
448: $url = "https://app.rakuten.co.jp/services/api/Travel/SimpleHotelSearch/20170426?datumType=1&applicationId={$appid}&affiliateId={$affid}&format=xml&latitude={$latitude}&longitude={$longitude}&searchRadius={$searchRadius}&responseType=large";
449:
450: // 絞り込み条件
451: foreach ($squeezeConditions as $key=>$val) {
452: if ($key == 0) {
453: $url .= "&squeezeCondition={$val}";
454: } else {
455: $url .= ",{$val}";
456: }
457: }
458:
459: return $url;
460: }
pahooRakuten.php
489: /**
490: * 楽天トラベル系API を利用してホテルを検索する
491: * @param array $items 情報を格納する配列
492: * @param float $latitude 緯度(世界測地系)
493: * @param float $longitude 経度(世界測地系)
494: * @param int $searchRadius 検索半径,単位km
495: * @param array $squeezeConditions 絞込み条件の配列:省略可能
496: * @param string $checkin チェックイン年月日(YYYY-MM-DD):省略可能
497: * @param string $checkout チェックアウト年月日(YYYY-MM-DD):省略可能
498: * @return ヒットした件数/FALSE:検索に失敗
499: */
500: function searchHotels(&$items, $latitude, $longitude, $searchRadius, $squeezeConditions=array(''), $checkin='', $checkout='') {
501: // 楽天トラベル空室検索API
502: if (preg_match('/\d{4}\-\d{2}\-\d{2}/i', $checkin) > 0) {
503: $url = $this->searchVacanthotelsURL($latitude, $longitude, $searchRadius, $checkin, $checkout);
504: // 楽天トラベル施設検索API
505: } else {
506: $url = $this->searchHotelsURL($latitude, $longitude, $searchRadius, $squeezeConditions);
507: }
508:
509: // APIコール
510: if (($res = $this->callWebAPI($url)) == FALSE) {
511: $this->error = TRUE;
512: $this->errmsg = 'WebAPI呼び出しに失敗';
513: return FALSE;
514: }
515: $this->webapi = $url;
516:
517: // PHP4用; DOM XML利用
518: if ($this->isphp5over() == FALSE) {
519: if (($dom = domxml_open_mem($res)) == NULL) {
520: $this->error = TRUE;
521: $this->errmsg = '楽天トラベルAPIの不具合';
522: $this->hits = 0;
523: return FALSE;
524: }
525: $pagingInfo = $dom->get_elements_by_tagname('pagingInfo');
526: // レスポンス・チェック
527: if (! is_object($pagingInfo )) {
528: $this->error = TRUE;
529: $this->errmsg = 'ホテルが見当たらない';
530: $this->hits = 0;
531: return FALSE;
532: }
533: $rc = $pagingInfo[0]->get_elements_by_tagname('recordCount');
534: if (! is_object($rc)) {
535: $this->error = TRUE;
536: $this->errmsg = 'ホテルが見当たらない';
537: $this->hits = 0;
538: return FALSE;
539: }
540: $rc = (int)$rc[0]->get_content();
541: if ($rc <= 0) {
542: $this->error = TRUE;
543: $this->errmsg = 'ホテルが見当たらない';
544: $this->hits = 0;
545: return FALSE;
546: }
547: // 検索結果取りだし
548: $hotels = $dom->get_elements_by_tagname('hotels');
549: $hotel = $hotels[0]->get_elements_by_tagname('hotel');
550: $cnt = 1;
551: foreach ($hotel as $val) {
552: foreach ($this->RakutenHotelItems as $name) {
553: $node = $val->get_elements_by_tagname('hotelBasicInfo');
554: $node = $node[0]->get_elements_by_tagname($name);
555: if ($node != NULL) {
556: $items[$cnt][$name] = (string)$node[0]->get_content();
557: }
558: }
559: $items[$cnt]['id'] = $this->num2alpha($cnt);
560: $items[$cnt]['title'] = $items[$cnt]['hotelName'];
561: $items[$cnt]['description'] =<<< EOT
562: <a href="{$items[$cnt]['hotelInformationUrl']}" target="_blank">{$items[$cnt]['hotelName']}</a> ({$items[$cnt]['address1']}{$items[$cnt]['address2']})
563: EOT;
564: $cnt++;
565: }
566:
567: // PHP5用; SimpleXML利用
568: } else {
569: $xml = simplexml_load_string($res);
570: if ($xml == '' || $xml == FALSE) {
571: $this->error = TRUE;
572: $this->errmsg = '楽天トラベルAPIの不具合';
573: $this->hits = 0;
574: return FALSE;
575: }
576: // レスポンス・チェック
577: if ($xml->pagingInfo->recordCount <= 0) {
578: $this->error = TRUE;
579: $this->errmsg = 'ホテルが見当たらない';
580: $this->hits = 0;
581: return FALSE;
582: }
583: // 検索結果取りだし
584: $cnt = 1;
585: $hotel = $xml->hotels->hotel;
586: foreach ($hotel as $element) {
587: foreach ($this->RakutenHotelItems as $name) {
588: if (isset($element->hotelBasicInfo->$name)) {
589: $items[$cnt][$name] = (string)$element->hotelBasicInfo->$name;
590: } else if (isset($element->hotelDetailInfo->$name)) {
591: $items[$cnt][$name] = (string)$element->hotelDetailInfo->$name;
592: }
593: }
594: // 部屋設備情報取り出し
595: if (isset($element->hotelFacilitiesInfo->roomFacilities->item)) {
596: $node = $element->hotelFacilitiesInfo->roomFacilities->item;
597: $i = 0;
598: while (isset($node[$i])) {
599: $items[$cnt]['roomFacilities'][$i] = (string)$node[$i];
600: $i++;
601: }
602: }
603: // Googleマップ描画用
604: $items[$cnt]['id'] = $this->num2alpha($cnt);
605: $items[$cnt]['title'] = $items[$cnt]['hotelName'];
606: $items[$cnt]['description'] =<<< EOT
607: <a href="{$items[$cnt]['hotelInformationUrl']}" target="_blank">{$items[$cnt]['hotelName']}</a> ({$items[$cnt]['address1']}{$items[$cnt]['address2']})
608: EOT;
609: $cnt++;
610: }
611: }
612: $this->hits = $cnt - 1;
613:
614: return $this->hits;
615: }
旧APIの廃止について
- 楽天トラベル施設検索API
- Version(2009-10-20)
- Version(2009-09-09)
- Version(2008-11-13)
- Version(2007-11-21)
- 楽天トラベル施設情報API
- Version(2009-09-09)
- Version(2009-03-26)
- Version(2008-11-13)
- Version(2007-11-21)
- Version(2007-04-11)
- 楽天トラベル空室検索API
- Version (2009-10-20)
- 楽天トラベル地区コードAPI
- Version (2009-03-26)
- 楽天トラベルキーワード検索API
- Version(2009-10-20)
- Version(2009-09-09)
- 楽天トラベルホテルチェーンAPI
- Version(2009-05-12)
- 楽天トラベルランキングAPI
- Version(2009-06-25)
参考サイト
- 楽天トラベル施設検索API
- PHPで最寄り駅を求める:ぱふぅ家のホームページ
- PHPセキュリティ対策:SSL通信を行う:ぱふぅ家ホームページ

なお、Yahoo! JavaScriptマップは、2020年(令和2年)10月31日をもってサービスを終了しており利用できない。
(2025年12月6日)PHP8.5対応:double→float表記変更,curl_closeを実行しないようにした
(2025年8月14日).pahooEnv導入
(2025年6月14日)GoogleMaps JavaScript APIの変更に対応した.