CakePHPでGeocoding

庄司です。

yahoo mapsやgoogle mapsで提供されているGeocoding APIを使って、世界の都市名と緯度・経度情報をマッピングした静的なテーブルを作成してみます。プログラムはCakePHPを使って作成します。

Geocoding APIは住所情報から緯度・経度情報を取得するAPIです。
今回はyahoo maps のAPIを利用します。

せっかくなのでCakePHPで作ってみようと思い参考情報をBakeryで探していた所、Geocoding APIを利用しているコードがあったので参考にします。

the Bakery: Geocoding in CakePHP
http://bakery.cakephp.org/articles/view/geocoding-in-cakephp

国・都市情報は
MaxMind社が配布しているGeoIP APIライブラリにデータがあるのでそれを利用します。

MaxMind社ダウンロードページ
http://www.maxmind.com/download/geoip/api/php/

利用するライブラリは以下の二つです。
geoip.inc
geoipregionvars.php


CakePHP(1.2)でテーブルにデータを突っ込むバッチプログラムを作ってみました。

<?php
/**
 * CakePHP batch
 */
class ImportGeo2Shell extends Shell {

    var $uses = array('Country', 'City');

    // Yahoo MAPs API
    var $yahoo_geocode_api_url = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=%key&location=%address';
    var $yahoo_maps_api_key    = 'YAHOO MAPs API KEY';

    function main()
    {
        /**
         * include geoip library
         */
        require_once VENDORS . 'geoip/geoip.inc';
        require_once VENDORS . 'geoip/geoipregionvars.php';

        $geo_ip = new GeoIP();

        foreach ($geo_ip->GEOIP_COUNTRY_CODES as $country_code) {
            if(!$country_code) {
                continue;
            }
           
            $country_number = $geo_ip->GEOIP_COUNTRY_CODE_TO_NUMBER[$country_code];
            $country_name   = $geo_ip->GEOIP_COUNTRY_NAMES[$country_number];

            $this->Country->save(array(
                'Country' => array(
                    'id' => null,
                    'name' => $country_name,
                    'name_short' => $country_code),
                'City' => array(),
            ));

            $country_id = $this->Country->getLastInsertID();

            if (!isset($GEOIP_REGION_NAME[$country_code])) {
                continue;
            }
           
            foreach ($GEOIP_REGION_NAME[$country_code] as $city_code => $city_name) {
                // geocoding city
                $yahoo_geocode_api_url = r(array('%key', '%address'),
                                           array($this->yahoo_maps_api_key,
                                                 rawurlencode($city_name . ' ' . $country_name)),
                                           $this->yahoo_geocode_api_url);
               
                $xmlstring = file_get_contents($yahoo_geocode_api_url);
                $simplexml = simplexml_load_string($xmlstring);
               
                if (!$simplexml->Result->Latitude || !$simplexml->Result->Longitude) {
                    echo "ERROR: Can't geocoding: $address\n";
                    continue;
                }
               
                $this->City->save(array(
                    'City' => array(
                        'id' => null,
                        'country_id' => $country_id,
                        'name' => $city_name,
                        'lat' => $simplexml->Result->Latitude,
                        'lng' => $simplexml->Result->Longitude)
                ));
            }
        }
    }
}

※yahoo八分にならないようにご注意下さい。