問題描述
在 CakePHP (v3) 應用程序中,如何根據傳遞的 lat lng 值檢索最接近的結果?
In a CakePHP (v3) application, how can I retrieve the closest results based on passed lat lng values?
我想讓它們作為本地 CakePHP 實體返回,所以是這樣的:
I'd like to have them back as native CakePHP entities, so something like this:
public function closest($lat, $lng) {
$sightings = //records within given lat lng
$this->set(compact('sightings'));
$this->set('_serialize', ['sightings']);
}
我知道這個 SQL 有效:
I know this SQL works:
SELECT *,
( 3959 * acos( cos( radians(50.7) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-1.8) ) + sin( radians(50.7) ) * sin( radians( latitude ) ) ) ) AS distance
FROM sightings
HAVING distance < 10
ORDER BY distance
LIMIT 0 , 20
努力將兩者結合起來.
更新
我已經添加了
class Sighting extends Entity {
public $_virtual = ['distance'];
//rest of class...
}
所以現在 distance
出現在我的 json 輸出中(現在預期值為 null,但我覺得這至少是一個步驟).
So now the distance
is showing up in my json output (with the value of null as would be expected right now, but I feel it's a step at lease).
我看過這里:http://www.mrthun.com/2014/11/26/search-distance-cakephp/ 這似乎是我想要實現的,所以假設是這樣的:
I've taken a look here: http://www.mrthun.com/2014/11/26/search-distance-cakephp/ which seems to be what I'm trying to achieve so assumed something like this:
$latitude = 51.145;
$longitude = -1.45;
$distance = 100;
$this->Sightings->virtualFields
= array('Sightings.distance'
=> '(3959 * acos (cos ( radians('.$latitude.') )
* cos( radians( Sightings.latitude ) )
* cos( radians( Sightings.longitude )
- radians('.$longitude.') )
+ sin ( radians('.$latitude.') )
* sin( radians( Sightings.latitude ) )))');
$sightings = $this->Sightings->find('all', [
'conditions' => ['Sightings.distance <' => $distance]
]);
$this->set(compact('sightings'));
$this->set('_serialize', ['sightings']);
結果:Column not found: 1054 Unknown column 'Sightings.distance' in 'where子句'
不確定是否可以使用 CakePHP v2 而不是 v3?
Not sure if it's possible CakePHP v2 as opposed to v3?
推薦答案
cake 3 中不再有 virtualFields,但您仍然可以為計算字段創建別名
there are no more virtualFields in cake 3 but you still can create an alias for your calculated field
按照@ndm 的建議,您最好綁定 $latitude
和 $longitude
以防止 SQL 注入
As suggested by @ndm you'd better bind $latitude
and $longitude
to prevent SQL injections
$distanceField = '(3959 * acos (cos ( radians(:latitude) )
* cos( radians( Sightings.latitude ) )
* cos( radians( Sightings.longitude )
- radians(:longitude) )
+ sin ( radians(:latitude) )
* sin( radians( Sightings.latitude ) )))';
使用where
$sightings = $this->Sightings->find()
->select([
'distance' => $distanceField
])
->where(["$distanceField < " => $distance])
->bind(':latitude', $latitude, 'float')
->bind(':longitude', $longitude, 'float')
->contain(['Photos', 'Tags']);
使用擁有
$sightings = $this->Sightings->find()
->select([
'distance' => $distanceField
])
->having(['distance < ' => $distance])
->bind(':latitude', $latitude, 'float')
->bind(':longitude', $longitude, 'float')
->contain(['Photos', 'Tags']);
這篇關于CakePHP 從數據庫查詢最近緯度經度的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!