最近ちょっとアレな感じでブログが滞ってます。最近ネタ切れ気味でありましたけど、これだけ頻繁に書いていると書いてみたくなるもんで、プログラム書きながらどうやってブログ書こうかなとか考えてました。忙しかったのは、プログラム書く事でもデザインでもなく、4800行のデータ入力と、それの確認が一番忙しかったです。もうデータ入力嫌です。嫌だからもう酒飲んで書いてます。本日3杯目です。というわけで、今日はこないだのジオロケーションの続きで、逆ジオコーディングというやつをやります。逆ジオコーディングっていうのは、グーグルさんによれば、地図上の地点を人が判読できる住所に変換するプロセスということらしいです。リバースコーディングとか言ったりしますが、英語にしただけです。
INDEX
緯度、経度を検索する
これはgeolocationAPIというのを使ってやります。が、これはちょっと前に書いた記事にやり方が全部載ってるので省略します。
グーグルからAPIを取得する
緯度経度から住所を取得したい場合、グーグルのAPIを使います。これをXMLHttpRequestを使ってやると、クロスドメインのoriginがつくエラーが出るので、scriptタグを使ってAPIを使います。こんな感じでやります。
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
こんな感じで良いんじゃないでしょうか。こうすることによって、逆ジオコーディングに必要なオブジェクトを呼ぶ事が出来ます。
流れとしては「緯度、経度を取得する」→「住所を取得する」→「phpに投げてtxtに保存する」って感じでやって行きたいと思います。
緯度、経度から住所を取得する
緯度、経度を取得して、googlemapのAPIが呼べた所で、コーディングをして行きます。この時点でコードはこんな感じになっています。
navigator.geolocation.getCurrentPosition(okCallback, erCallback); //成功時に実行される function okCallback(pos) { //posに経度と緯度が入ってくる lat = pos.coords.latitude lng = pos.coords.longitude function reverseGeo(lat,lng) { var geoObj; geoObj = new google.maps.Geocoder() var latlng = new google.maps.LatLng(lat,lng) if (geoObj) { geoObj.geocode({'latLng': latlng}, function(results, status) { if(status == "OK") { alert(results[0].formatted_address) } else { alert(status) } }); } } reverseGeo(lat,lng) }
geocodeオブジェクトを使うと、googleのapiから回答を受け取るコールバック関数を扱う事ができます。コールバック関数っていうのは、呼び出した関数が実行する関数です。LatLngメソッドは、緯度経度をAPIが理解できる形に整形してくれるもんだと思ってます。このメソッドを使うと、緯度を度で、経度を度で返します。三つ目の引数にtrueを入れると、範囲外の値を修正しませんが、多分あんまし三つ目の引数は気にしなくて良いんだと思います。この引数のresultsから.formatted_addressプロパティを参照すれば住所を取得することができます。
メソッド等の詳しい説明
Google Maps API V3
ジオコーディング サービス
phpにpostする
HTTPとはWebサーバーがユーザーからのリクエストや送信に応答する方法を規定したものです。普通HTTP通信が行われるのはユーザがリクエストを要求した時です。リンクをクリックしたり、フォームを送信したり、URLを入力したりそういう時ですが、これらをjavascriptが制御する事ができます。なのでjavascriptからphpにデータを渡す事も可能です。こんな感じでやります。
var xhr = new XMLHttpRequest() xhr.open("POST","test.php",true) xhr.setRequestHeader("Content-Type" , 'application/x-www-form-urlencoded') //これつけないとエラーになる xhr.send('data='+resAddress) xhr.onreadystatechange = function () { if(xhr.readyState == 4 && xhr.status == 200) { //これやらないと.responseTextが三回帰ってくる var resTxt = xhr.responseText console.log(resTxt) alert(resTxt) } }
XMLHttpRequestは今は全てのブラウザでサポートされています。このオブジェクトには、HTTPを制御するAPIが定義されています。ちなみにこのXMLHttpRequestのXMLっていうのは当時流行だったからつけたらしいです。openメソッドはリクエストを初期化するメソッドで引数は5つつける事が出来ます。1つめがメソッド、2つ目がurl、3つめが、非同期かどうかで4つ目と5つ目は認証がある場合userとpasswordを指定します。詳しくは、MDNみてください。sendでデータを送りますが、データの形式はdata=値みたいにしないと駄目みたいです。二つ以上渡したい場合はhoge=value&hoge2=valueみたいにすれば良いと思われます。ちなみにこうして送信されるデータはmimeタイプを持つので、 xhr.setRequestHeader("Content-Type" , 'application/x-www-form-urlencoded')これが必要になります。
サーバーにデータを保存する
こっからはphpのコードを書きます。
<?php $processMessage = array('ok' => '書き込めました','ng' => '書き込めませんでした。'); $getPost = htmlspecialchars($_POST['data']); list($pref,$city) = explode(',',$getPost); if(gettype($pref) == 'string' && gettype($city) == 'string') : $address = explode(' ',ltrim($city)); foreach($address as $val) : if(preg_match('/^〒\d{3}-\d{4}$/', $val, $match)) : $zipCode = array_shift($address); else : echo $val."\n"; endif; endforeach; if(file_put_contents('test.txt', implode(',',$address)."\n", FILE_APPEND | LOCK_EX)) : echo $processMessage['ok']; else : echo $processMessage['ng']; endif; else : echo $processMessage['ng']; endif;
APIから取得してくるデータが日本,住所みたいな感じなのでまず,を基準に配列にして、変数にぶちこんでます。変数に入れた値の型をシャレ程度にstringかどうか聴いて、取得するデータが郵便番号 住所1 住所2 住所3 みたいになってるので今度は半角スペースを基準に配列化します。で、今回郵便番号はテキストに保存したくないので、こいつを取っ払う為にpreg_matchで一致した奴はzipって変数に退避させています。そして、file_put_contentsでデータを書き込みする訳ですが、FILE_APPENDで追記するようにできて、LOCK_EXする事で同時に書き込む事を不可能にできるので、こういう風にしてます。implodeで配列を再結合して、これを一行として入力しています。文章で書くと全然意味不明ですが、とりあえず、こうやってやるとサーバーにXMLHttpRequestから渡されたデータを保存できます。
ちなみに!その他の人の書き込み権限をオッケーにしておかないと書き込みが出来ないので、パーミッションの変更をchownなりファイル転送ソフトなりで変更してください!どうでもいいですけど、XMLHttpRequestって名前長いですよねー。