CakePHP从数据库查询最近纬度经度

Kyl*_*lan 12 php mysql location cakephp cakephp-3.0

在CakePHP(v3)应用程序中,如何根据传递的lat lng值检索最接近的结果?

我想让它们作为本机CakePHP实体返回,所以像这样:

public function closest($lat, $lng) {

    $sightings = //records within given lat lng 

    $this->set(compact('sightings'));
    $this->set('_serialize', ['sightings']);
}
Run Code Online (Sandbox Code Playgroud)

我知道这个SQL有效:

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
Run Code Online (Sandbox Code Playgroud)

苦苦挣扎将两者结合起来.

UPDATE

我已经添加

class Sighting extends Entity {
    public $_virtual = ['distance'];
    //rest of class...
}
Run Code Online (Sandbox Code Playgroud)

所以现在distance它出现在我的json输出中(正如预期的那样,值为null,但我觉得这是一个步骤).

我在这里看了一下:http://www.mrthun.com/2014/11/26/search-distance-cakephp/这似乎是我想要实现的,所以假设这样的事情:

$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']);
Run Code Online (Sandbox Code Playgroud)

结果是: Column not found: 1054 Unknown column 'Sightings.distance' in 'where clause'

不确定CakePHP v2是否可能与v3相对吗?

ari*_*lia 10

蛋糕3中不再有虚拟字段,但您仍可以为计算字段创建别名

正如@ndm所建议的那样,你最好绑定$latitude$longitude防止SQL注入

$distanceField = '(3959 * acos (cos ( radians(:latitude) )
    * cos( radians( Sightings.latitude ) )
    * cos( radians( Sightings.longitude )
    - radians(:longitude) )
    + sin ( radians(:latitude) )
    * sin( radians( Sightings.latitude ) )))';
Run Code Online (Sandbox Code Playgroud)

在哪里使用

$sightings = $this->Sightings->find()
    ->select([
        'distance' => $distanceField
    ])
    ->where(["$distanceField < " => $distance])
    ->bind(':latitude', $latitude, 'float')
    ->bind(':longitude', $longitude, 'float')
    ->contain(['Photos', 'Tags']);
Run Code Online (Sandbox Code Playgroud)

使用

$sightings = $this->Sightings->find()
    ->select([
        'distance' => $distanceField
    ])
    ->having(['distance < ' => $distance])
    ->bind(':latitude', $latitude, 'float')
    ->bind(':longitude', $longitude, 'float')
    ->contain(['Photos', 'Tags']);
Run Code Online (Sandbox Code Playgroud)


Obj*_*tor 0

这里需要使用ConnectionManager。

例如:

use Cake\Datasource\ConnectionManager;  // Mention this first, preferably on top of the page.

$connection = ConnectionManager::get('default');

$results = $connection
  ->execute('SELECT * FROM articles WHERE id = :id', ['id' => 1])
  ->fetchAll('assoc');
Run Code Online (Sandbox Code Playgroud)

您可以尝试以这种方式设置查询。它肯定会起作用。

以此作为参考:

CakePHP 3 的 SELECT 语句