0

Im trying to build a small CakePHP website which has some lat and longitudes in the DB. A user performs a search query to locations (with giving her/his address) and the results needs to be ordered by distance from user to the location. I can already get the lat en lng when providing an adress (using the Google Maps API). I'm not sure how to build a CakePHP find with an distance order. Any ideas?

I'm using CakePHP 2.3.

Marco Veenendaal
  • 186
  • 1
  • 12
  • if u r using google maps, you can use the [distance matrix](https://developers.google.com/maps/documentation/distancematrix/). – Kishor Kundan Mar 16 '13 at 12:39

2 Answers2

2

I prefer to use virtualFields for this purpose. The implementation depends on DB you use. For Postgres it will look like following:

MyModel.php

public function findSortedByDistanse($long, $lat){
    $distanceValue = "calc_distance($lat, $long, MyModel.lat, MyModel.lon)";
    $this->virtualFields['distance'] = $distanceValue;
    return $this->find('all', array('conditions' => array(
        'order' => 'MyModel.distance ASC'
    )));
}

where calc_distance is a stored procedure for Postgres

Params: IN source_lat numeric, IN source_lon numeric, IN target_lat numeric, IN target_lon numeric

Code:

SELECT ( 3956 * 2 * 
   ASIN ( 
      SQRT ( 
        POWER ( SIN ( ( $1 - abs($3) ) * pi()/180/2 ),2 ) + 
        COS ( $1 * pi()/180 ) * 
    COS ( abs($3) * pi()/180 ) * 
    POWER ( SIN ( ( $2 - $4 ) * pi()/180 / 2 ), 2 ) 
      ) 
   )
)

If you prefer raw query, use following:

$distanceValue = "3956 * 2 * ASIN(SQRT(POWER(SIN(({$lat}-abs(MyModel.lat))*pi()/180/2),2)+COS({$lat} * pi()/180)*COS(abs(MyModel.lat) *  pi()/180)*POWER(SIN(({$long} - MyModel.lon)*pi()/180 / 2), 2)))";
Karisters
  • 186
  • 5
0

Rangeable can be used to find near-by based on user's chosen GeoLocation. However, this plugin is deprecated because it is made to support CakePHP 1.x and may not work with CakePHP 2.x .

You might need to convert it.

Keval Domadia
  • 4,768
  • 1
  • 37
  • 64