Yahoo!ジオコーダAPI | CURL版により緯度経度取得率を高める
※2023年6月の時点において、CURLの方法は失敗するようだ。
file_get_contentsでは緯度経度取得に失敗することが多々ある。
CURLを用いると成功率はかなり高まるようだ。
PHP(CakePHP2)
/**
* 一括緯度経度取得・バッチ処理 | Ajax 非同期通信
* @return string json
*/
public function bulk_latlng_bat(){
$this->autoRender = false;//ビュー(ctp)を使わない。
// 通信元から送信されてきたパラメータを取得する。
$param_json = $_POST['key1'];
$ent = json_decode($param_json,true);//JSON文字を配列に戻す
$place = "東京都墨田区押上1丁目1-2";
$place = preg_replace("/( | )/", "", $place); // 住所中の空白を除去すると緯度経度取得の成功率が高まる。
// $app_id = Configure::read('yahoo_api_key'); // Yahoo APIキー
$app_id = 【あなたのAPIキー】
// Yahoo!ジオコーダAPIを利用して住所から緯度経度を取得する (住所によっては緯度経度が取得できないケースもあり)
$base_url = "https://map.yahooapis.jp/geocode/V1/geoCoder?output=xml&appid={$app_id}";
$param = '&query=' . $place;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $base_url. $param);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$xml_str = curl_exec($curl);
// XMLをパースして配列データに変化する
$geoData =$this->xml2arr($xml_str);
$find_flg = false; // true:緯度経度が見つかる, false:緯度経度が見つからない
$lat = 0; // 緯度
$lng = 0; // 経度
if(!empty($geoData['Feature'])){
if(!empty($geoData['Feature']['Geometry'])){
if(!empty($geoData['Feature']['Geometry']['Coordinates'])){
$find_flg = true;
$coordinates = $geoData['Feature']['Geometry']['Coordinates'];
$ary=explode(",", $coordinates);
$lat = trim($ary[1]);
$lng = trim($ary[0]);
}
}
}
・・・省略・・・
}
/**
* XMLテキストからデータ配列に変換する
*
* @note
* 多層構造であるとき、階層化の配列が0件でであるなら0件配列でなく空文字がセットされる。
* JSONとは完全な互換性はないので注意すること。
*
* @param string $xml_text XMLテキスト
* @return データ配列
*/
public function xml2arr($xml_text){
// XML解析
$data= new SimpleXMLElement($xml_text,
LIBXML_COMPACT | LIBXML_NOERROR,
false);
// SimpleXMLElementオブジェクト型から配列データに変換する
$this->obj2arr($data);
return $data;
}
/**
* SimpleXMLElementのレスポンスのオブジェクトをデータ配列に変換する。
*
* @note
* 階層化の配列が0件である場合、0件配列でなく、空文字がセットされる。
* 高速化のため引数を参照型しており、レスポンスも兼ねている。
*
* @param array $data SimpleXMLElementオブジェクト → 配列データ
*/
private function obj2arr(&$data){
if(is_array($data)){
foreach($data as $i => &$chiled){
$this->obj2arr($chiled);
}
unset($chiled);
}elseif(is_object($data)){
$count = $data->count();
if(empty($count)){
$data = '';
}else{
$data = get_object_vars($data);
foreach($data as $i => &$chiled){
$this->obj2arr($chiled);
}
unset($chiled);
}
}
}