DBに緯度と経度がある小さなCakePHP Webサイトを構築しようとしています。ユーザーは場所に対して検索クエリを実行し (住所を入力して)、結果はユーザーから場所までの距離で並べ替える必要があります。(Google Maps APIを使用して)住所を提供するときに、すでに緯度経度を取得できます。距離順で CakePHP 検索を作成する方法がわかりません。何か案は?
CakePHP 2.3 を使用しています。
DBに緯度と経度がある小さなCakePHP Webサイトを構築しようとしています。ユーザーは場所に対して検索クエリを実行し (住所を入力して)、結果はユーザーから場所までの距離で並べ替える必要があります。(Google Maps APIを使用して)住所を提供するときに、すでに緯度経度を取得できます。距離順で CakePHP 検索を作成する方法がわかりません。何か案は?
CakePHP 2.3 を使用しています。
この目的には virtualFields を使用することを好みます。実装は、使用する DB によって異なります。Postgres の場合、次のようになります。
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'
)));
}
ここで、calc_distance は Postgres のストアド プロシージャです。
パラメータ: IN source_lat 数値、IN source_lon 数値、IN target_lat 数値、IN target_lon 数値
コード:
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 )
)
)
)
生のクエリを好む場合は、次を使用します。
$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)))";
Rangeableを使用して、ユーザーが選択した GeoLocation に基づいて近くを見つけることができます。ただし、このプラグインは CakePHP 1.x をサポートするように作成されており、CakePHP 2.x では動作しない可能性があるため、非推奨です。
変換する必要があるかもしれません。