Created
November 22, 2014 11:52
-
-
Save dljoseph/ee3712eda3fb5c4b6820 to your computer and use it in GitHub Desktop.
SilverStripe 3.1.x Store locator snippet - grabs lat/lng from Google
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Store extends DataObject { | |
static $db = array( | |
'Title' => "Varchar(128)", | |
'Name' => "Varchar(128)", | |
'Address1' => "Varchar(128)", | |
'Address2' => "Varchar(128)", | |
'Address3' => "Varchar(128)", | |
'PostCode' => "Varchar(10)", | |
"Phone" => "Varchar(16)", | |
"Lat" => "Float(10,9)", | |
"Lng" => "Float(10,9)" | |
); | |
private static $summary_fields = array( | |
'Title', | |
'Name', | |
'Address1', | |
'Address2', | |
'Address3', | |
'PostCode', | |
'Lat', | |
'Lng' | |
); | |
public function getCMSFields() | |
{ | |
$fields = parent::getCMSFields(); | |
return $fields; | |
} | |
public function onBeforeWrite() { | |
if (!$this->ID || $this->isChanged()) { | |
//get the lat and long values for the address | |
//$address = $this->Title ? $this->Title .',' : ''; | |
$address = $this->Address1 ? $this->Address1 .',' : ''; | |
$address .= $this->Address2 ? $this->Address2 .',' : ''; | |
$address .= $this->Address3 ? $this->Address3 .',' : ''; | |
$address .= $this->PostCode; | |
$address = urlencode($address); | |
$region = 'GB'; | |
$json = file_get_contents("http://maps.google.com/maps/api/geocode/json?address=$address&sensor=false®ion=$region"); | |
$lat = $json->{'results'}[0]->{'geometry'}->{'location'}->{'lat'}; | |
$lng = $json->{'results'}[0]->{'geometry'}->{'location'}->{'lng'}; | |
if ($lat) { | |
$this->Lat = $lat; | |
} | |
if ($lng) { | |
$this->Lng = $lng; | |
} | |
} | |
parent::onBeforeWrite(); | |
} | |
} | |
class StoresService implements WebServiceable { | |
public function __construct() { | |
} | |
public function webEnabledMethods() { | |
return array( | |
'getStores' => 'GET', | |
); | |
} | |
public function getStores($lat = null, $lng = null) { | |
/* | |
* To find locations in your markers table that are within a certain radius distance of a given latitude/longitude, | |
* you can use a SELECT statement based on the Haversine formula. The Haversine formula is used generally for | |
* computing great-circle distances between two pairs of coordinates on a sphere. | |
* | |
* Here's the SQL statement that will find the closest 20 locations that are within a radius of 25 miles to | |
* the 37, -122 coordinate. It calculates the distance based on the latitude/longitude of that row and the target | |
* latitude/longitude, and then asks for only rows where the distance value is less than 25, orders the whole query | |
* by distance, and limits it to 20 results. To search by kilometers instead of miles, replace 3959 with 6371. | |
* | |
* SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance | |
* FROM tablename | |
* HAVING distance < 25 | |
* ORDER BY distance | |
* LIMIT 0 , 20; | |
* */ | |
if (is_numeric($lat) && is_numeric($lng)) { | |
$sqlQuery = new SQLQuery(); | |
$sqlQuery->setFrom('Store'); | |
$sqlQuery->selectField('( 3959 * acos( cos( radians('.$lat.') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('.$lng.') ) + sin( radians('.$lat.') ) * sin( radians( lat ) ) ) )','distance'); | |
//$sqlQuery->selectField('concat(Title, " ", Name)','storename'); //valid concat statement, but SS doesn't like it! | |
$sqlQuery->addHaving('distance < 25'); | |
$sqlQuery->setOrderBy('distance'); | |
$sqlQuery->setLimit(20); | |
$result = $sqlQuery->execute(); | |
$returnedRecords = new ArrayList(); | |
foreach($result as $row) { | |
$row['Name'] = $row['Title']. ' ' . $row['Name']; | |
unset($row['Title']); | |
$Address = ''; | |
$Address.= $row['Address1'] ? $row['Address1'] .', ' : ''; | |
$Address.= $row['Address2'] ? $row['Address2'] .', ' : ''; | |
$Address.= $row['Address3'] ? $row['Address3'].', ' : ''; | |
$Address.= $row['PostCode'] ? $row['PostCode'] : ''; | |
unset($row['Address1']); | |
unset($row['Address2']); | |
unset($row['Address3']); | |
//insert address line at offset 5 in associative array | |
$offset = 5; | |
$newArray = array_slice($row, 0, $offset, true) + | |
array('Address' => "$Address") + | |
array_slice($row, $offset, NULL, true); | |
$returnedRecords->push(new ArrayData($newArray)); | |
} | |
return array( | |
'Stores' => $returnedRecords, | |
); | |
} | |
return null; | |
} | |
} | |
class StoreAdmin extends ModelAdmin { | |
public static $managed_models = array( | |
'Store' | |
); | |
static $url_segment = 'store'; // will be linked as /admin/store | |
static $menu_title = 'Store Locations'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment