HTTPジオコーダ用ライブラリ(のサンプル)を作ってみました
こんにちは、シーブレインのinoueです。
今日は七夕。皆さんはどんな願い事をしましたか。
さて。日々進化を続けるGoogle Map APIにwebサイトやサービスは助けられっぱなしです。
特に住所から緯度経度情報を得られるジオコーディング機能はすばらしい!のひとこと。
このジオコーディング機能、webクライアント側だけでなく、HTTPリクエストを利用しても取得が可能です。
「旧システムで登録された住所情報に緯度経度情報を追加したい。対象となるデータは数千件!」なんて時に威力を発揮してくれそうなこの機能。
汎用的なクラスにしたら、いろいろと活躍してくれそう、ってことで、HttpGeocoderなるPHPのクラスを作ってみました。
本当に必要最小限なソースコードなので、利用される場合はエラー処理など適宜追加してください。
なお、サーバの設定によってはファイルアクセス関数が動作しない場合があります。その場合はこちらは使用できません。
<?php
/*
*
* HTTP Geocoder
*
* GoogleMap API を使った HTTPリクエスト経由のジオコーディングクラス
*/
class HttpGeocoder
{
var $request_url = "http://maps.google.com/maps/geo";
var $api_key = null; //
var $type_select = array("json", "xml", "kml", "csv");
function getValue($address, $type = 'json', $sensor = false)
{
//apiキー または 検索する住所が未設定ならば、処理を中断
if (empty($this->api_key) || empty($address)) {
return false;
}
//出力タイプは csv, xml, kml, json のいずれか
//それ以外ならば デフォルトの json にする
if (array_search($type, $this->type_select) === false) {
$type = "json";
}
$url = $this->request_url;
$url .= "?q=" . urlencode($address);
$url .= "&output=" . $type;
$url .= "&sensor=" . $sensor; //true_or_false
$url .= "&key=" . $this->api_key;
$handle = fopen($url, "r");
$buffer = "";
if ($handle) {
while (!feof($handle)) {
$buffer .= fgets($handle);
}
fclose($handle);
}
return $buffer;
}
}
?>
このHttpGeocoderをCakePHPに組み込んだサンプルがこちら。
Sampleコントローラのgeocodingアクションとして実装してみた場合です。
(ソースコードはいろいろと簡略化してあります。単なるコピーアンドペーストでは動かないと思いますのであらかじめご了承ください。)
// コントローラ sample_controller.php
class SampleController extends AppController
{
/**
* sample code
* ジオコーディング - 住所から地図検索
*/
function geocoding()
{
App::import('vendor','geocoder/http_geocoder');
$geo = new HttpGeocoder();
$geo->api_key = MY_GOOGLE_MAP_API_KEY; //取得したAPI KEYを設定する
$this->set('type_select',$geo->type_select);
if (empty($this->data)) {
return;
}
$address = $this->data['address'];
$type = $geo->type_select[$this->data['type']];
$result = $geo->getValue($address, $type);
switch ($type) {
case "json":
$obj_result = json_decode($result);
new dbug($obj_result);
$arr_result = $obj_result->Placemark[0]->Point->coordinates;
//緯度を取得
$latitude = $arr_result[1];
//経度を取得
$longitude = $arr_result[0];
break;
case "csv";
$arr_result = explode(',',$result);
//緯度を取得
$latitude = $arr_result[2];
//経度を取得
$longitude = $arr_result[3];
case "xml":
case "kml";
//(省略)
break;
}
$this->set('output',$result);
$this->set('latitude',$latitude);
$this->set('longitude',$longitude);
$this->set('address',$address);
}
}
// ビュー geocoding.ctp
<h1>住所から緯度経度を求める</h1>
<div class="searchInput">
<h2>検索条件</h2>
<?php e($form->create(null, array('action'=>'geocoding', 'type' => 'post')));?>
<table>
<tr>
<th>検索する住所</th>
<td>
<?php e($form->text('address',array('class'=>'sizeL')));?></td>
</tr>
<tr>
<th>出力データフォーマット</th>
<td><?php e($form->select("type", $type_select, NULL, array('class' => 'single'), '選択して下さい'));?></td>
</tr>
</table>
<ul class="setButton">
<li><?php e($form->submit('検索', array('div'=>false)));?></li>
</ul>
<?php e($form->end());?>
<!-- /.searchInput --></div>
<h2>取得したデータ</h2>
<p><?php e($output); ?></p>
<h2>検索結果</h2>
<div class="messageInfo">
<p><?php e($address ."は、<br />緯度:".$latitude ." 経度:". $longitude . "です。"); ?></p>
<!-- /.messageInfo --></div>
このサンプルを動かして、CSV形式とJSON形式でデータを取得、表示した結果がこちら。
単に緯度経度の値が必要な場合はCSV形式がおすすめです。
このライブラリを利用して、データベースから住所データを複数取得し、緯度経度情報を順次検索して結果を登録していく、という処理が可能になります。
ただし、このHTTPリクエスト経由のジオコーディング、利用制限が定められているのでご注意ください。
現在のところ24時間以内に15,000回を超えるリクエストはダメ、となっていますので、一括処理したいデータ件数が制限値を超える場合は、数日に処理を分割するなど対策が必要です。