Skip to content

Instantly share code, notes, and snippets.

@phackwer
Created June 7, 2017 17:59
Show Gist options
  • Save phackwer/a1dbb739e791e80442b52cb7a3840c23 to your computer and use it in GitHub Desktop.
Save phackwer/a1dbb739e791e80442b52cb7a3840c23 to your computer and use it in GitHub Desktop.
Laravel 5 - all cities, regions, states and countries from Gazeteer
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
/**
* @var array
*/
protected $fillable = ['country_id', 'state_id', 'region_id', 'name', 'latitude', 'longitude', 'created_at', 'updated_at'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function country()
{
return $this->belongsTo('App\Models\Country');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function state()
{
return $this->belongsTo('App\Models\State');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function region()
{
return $this->belongsTo('App\Models\Region');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
/**
* @var array
*/
protected $fillable = ['created_at', 'updated_at', 'name', 'latitude', 'longitude', 'code'];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function states()
{
return $this->hasMany('App\Models\State');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function regions()
{
return $this->hasMany('App\Models\Region');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function cities()
{
return $this->hasMany('App\Models\City');
}
}
<?php
use Illuminate\Database\Seeder;
/**
* GeoNames Gazetteer importer
* Queries http://www.geonames.org/childrenJSON?geonameId={LOCATIONCODE}&callback=listPlaces&style=long
* and import it into the Coutries, States and Cities for each continent
*
* Continent (highest level) codes
* 6255146 - Africa
* 6255147 - Asia
* 6255148 - Europe
* 6255149 - North America
* 6255150 - South America
* 6255151 - Oceania
* 6255152 - Antarctica
*
* fcode list
* PCL* = Country
* ADM1 = State / Province
* ADM2 = County / Region
* PPL* = City / Village
*/
class CountryStateCitySeeder extends Seeder
{
/**
* URL to retrieve data from
*/
protected $url = "http://www.geonames.org/childrenJSON?geonameId={LOCATION_CODE}&style=short&username={USERNAME}";
protected $username = ['demo', 'asdf', 'qwer', 'zxcv', 'sadf', 'wqer', 'xzcv', 'vcxz', 'fdsa', 'rewq', 'mode'];
protected $currUserIndex = 0;
/**
* Continent codes (continents are not imported)
*/
protected $contCodes = [
//6255146, // Africa
//6255147, // Asia
6255148, // Europe
//6255149, // North America
//6255150, // South America
//6255151, // Oceania
//6255152, // Antarctica
];
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$ds = DIRECTORY_SEPARATOR;
$path = base_path() . $ds .
'database' . $ds .
'seeds' . $ds .
'data' . $ds;
$filename = $path . 'geonames_gazeteer.tgz';
if (file_exists($filename)) {
exec('tar -zxvf ' . $filename . ' -C ' . $path);
sleep(10);
}
foreach ($this->contCodes as $code) {
$countries = $this->getList($code, 'country');
if (isset($countries->geonames)) {
foreach ($countries->geonames as $country) {
try {
$countryDb = new \App\Models\Country();
$countryDb->id = $country->geonameId;
$countryDb->name = $country->name;
$countryDb->latitude = $country->lat;
$countryDb->longitude = $country->lng;
$countryDb->code = $country->countryCode;
$countryDb->save();
} catch (\Exception $e) {
};
echo "Added country " . $country->name . "\n";
$states = $this->getList($country->geonameId, 'state');
if (isset($states->geonames)) {
foreach ($states->geonames as $state) {
try {
if (strstr($state->fcode, 'PPL')) {
$stateDb = new \App\Models\City();
} else {
$stateDb = new \App\Models\State();
}
$stateDb->id = $state->geonameId;
$stateDb->name = $state->name;
$stateDb->latitude = $state->lat;
$stateDb->longitude = $state->lng;
$stateDb->country_id = $countryDb->id;
$stateDb->save();
} catch (\Exception $e) {
};
if (strstr($state->fcode, 'PPL')) {
echo "Added city " . $state->name . " into country " . $country->name . "\n";
} else {
echo "Added state " . $state->name . " into country " . $country->name . "\n";
}
$regions = $this->getList($state->geonameId, 'region');
if (isset($regions->geonames)) {
foreach ($regions->geonames as $region) {
try {
if (strstr($region->fcode, 'PPL')) {
$regionDb = new \App\Models\City();
} else {
$regionDb = new \App\Models\Region();
}
$regionDb->id = $region->geonameId;
$regionDb->name = $region->name;
$regionDb->latitude = $region->lat;
$regionDb->longitude = $region->lng;
$regionDb->state_id = $stateDb->id;
$regionDb->country_id = $countryDb->id;
$regionDb->save();
} catch (\Exception $e) {
};
if (strstr($region->fcode, 'PPL')) {
echo "Added city " . $region->name . " into state " . $state->name . " into country " . $country->name . "\n";
} else {
echo "Added region " . $region->name . " into state " . $state->name . " into country " . $country->name . "\n";
}
$cities = $this->getList($region->geonameId, 'city');
if (isset($cities->geonames)) {
foreach ($cities->geonames as $city) {
echo "Added city " . $city->name . " into region " . $region->name . " state " . $state->name . " into country " . $country->name . "\n";
try {
$cityDb = new \App\Models\City();
$cityDb->id = $city->geonameId;
$cityDb->name = $city->name;
$cityDb->latitude = $city->lat;
$cityDb->longitude = $city->lng;
$cityDb->region_id = $regionDb->id;
$cityDb->state_id = $stateDb->id;
$cityDb->country_id = $countryDb->id;
$cityDb->save();
} catch (\Exception $e) {
};
}
}
}
}
}
}
}
}
}
}
public function getList($code, $type)
{
$ds = DIRECTORY_SEPARATOR;
$filename = base_path() . $ds .
'database' . $ds .
'seeds' . $ds .
'data' . $ds .
'geonames.org' . $ds .
'geonames_gazeteer_'
. $code
. '.json';
if (file_exists($filename)) {
$places = json_decode(file_get_contents($filename));
} else {
$url = str_replace('{LOCATION_CODE}', $code, $this->url);
$url = str_replace('{USERNAME}', $this->username[$this->currUserIndex], $url);
$places = file_get_contents($url);
$places = json_decode($places);
if (isset($places->status) && $places->status->value == 19) {
$this->currUserIndex++;
$this->currUserIndex = ($this->currUserIndex < count($this->username)) ? $this->currUserIndex : 0;
echo "Resting until API is freed again: $url\n";
return $this->getList($code, $type);
}
file_put_contents($filename, json_encode($places));
}
return $places;
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Region extends Model
{
/**
* @var array
*/
protected $fillable = ['country_id', 'state_id', 'created_at', 'updated_at', 'name', 'latitude', 'longitude'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function country()
{
return $this->belongsTo('App\Models\Country');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function state()
{
return $this->belongsTo('App\Models\State');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function cities()
{
return $this->hasMany('App\Models\City');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class State extends Model
{
/**
* @var array
*/
protected $fillable = ['country_id', 'created_at', 'updated_at', 'name', 'latitude', 'longitude'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function country()
{
return $this->belongsTo('App\Models\Country');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function regions()
{
return $this->hasMany('App\Models\Region');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function cities()
{
return $this->hasMany('App\Models\City');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment