查询范围以获取最新关系模型满足条件的模型

时间:2019-02-01 21:19:30

标签: php laravel eloquent

我想获得最近(最后添加)相关位置在特定区域内的自行车。这应该使用自行车模型上的查询范围scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest)完成。每辆自行车都有很多位置:

public function locations()
{
      return $this->hasMany(Location::class);
}

到目前为止,我所拥有的一切似乎根本不起作用,因为我不知道如何只检查最新的相关位置。

public function scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest)
{
      return $query->whereHas('locations', function ($q) use ($latNorth, $lonEast, $latSouth, $lonWest)
      {
          $q->whereBetween('latitude', [$latNorth, $latSouth])
            ->whereBetween('longitude', [$lonWest, $lonEast]);
      });
}

退回的自行车的最新位置不符合whereBetween条件。

选择位置而不选择关联的自行车将按预期工作:

App\Location::whereBetween('latitude', [50, 50.2])->whereBetween('longitude', [11, 12])->get();

更新:

位置模型具有经度和纬度字段:

$table->decimal('latitude', 8, 6);
$table->decimal('longitude', 9, 6);

作用域的用法如下:

$bounding_bikes = Bike::bounding($latNorth, $lonEast, $latSouth, $lonWest)->get();

a similar question

2 个答案:

答案 0 :(得分:0)

我认为您应该尝试像获取特定自行车两点之间的距离之类的方法,然后可以对距离进行过滤。

我假设在这里您将拥有location表,而lat和lng应该是该表中的列。

这将以公里为单位计算距离

public function scopeBounding($query, $from_latitude, $from_longitude, $distance)
{
  $raw = \DB::raw('ROUND ( ( 6371 * acos( cos( radians('.$from_latitude.') ) * cos( radians( locations.lat ) ) * cos( radians( locations.lng ) - radians('.$from_longitude.') ) + sin( radians('.$from_latitude.') ) * sin( radians( locations.lat ) ) ) ) ) AS distance');

  return $query->select($raw)->orderBy( 'distance', 'asc' )->having('distance', '<=', $distance)
}

答案 1 :(得分:0)

我终于找到的解决方案对我来说确实很难看,但我没有发现更好的方法:

public function scopeBounding($query, $latNorth, $lonEast, $latSouth, $lonWest)
{
      return $query->whereHas('locations', function ($q) use($latNorth, $lonEast, $latSouth, $lonWest) {
        $q->whereRaw('`locations`.`id` = (select `locations`.`id` from `locations` where `bikes`.`id` = `locations`.`bike_id` order by `created_at` desc limit 1)')
          ->whereBetween('latitude', [$latSouth, $latNorth])
          ->whereBetween('longitude', [$lonWest, $lonEast]);
      });
}

所以我很乐意提供任何简化方法的想法!