Как получить соседних пользователей и расстояния? - PullRequest
0 голосов
/ 05 сентября 2018

Сначала я хочу показать вам текущую структуру базы данных. Есть две таблицы:

Пользователи

  • ID
  • имя
  • LOCATION_ID

Места

  • ID
  • город
  • ш
  • LNG

Теперь я хочу реализовать API, который получает соседних пользователей и их расстояние. Понравилось соседним пользователям:

{{name:user1,distance:5km},(name:user2,distance:7 km)}

1 Ответ

0 голосов
/ 05 сентября 2018

Вы можете попробовать это так

Модель пользователя

public function location(){
    return $this->belongsTo('App\Location');
}

В модели Location создайте имя функции rsine, а затем создайте локальную область с именем scopeIsWithinMaxDistance, например

Модель местоположения

/**
 * Scope for adding distance filter
 */
public function scopeIsWithinMaxDistance($query, $rsine, $radius = 5)
{
    return $query->selectRaw("*, {$rsine} AS distance")
                 ->whereRaw("{$rsine} < ?", [$radius])
                 ->orderBy('distance');
}

/**
 * Sql command for finding distance between 2 coordinates
 */
public static function rsine($coordinates)
{
    return '(6371 * acos(cos(radians(' . $coordinates['latitude'] . ')) 
    * cos(radians(`lat`)) 
    * cos(radians(`lng`) 
    - radians(' . $coordinates['longitude'] . ')) 
    + sin(radians(' . $coordinates['latitude'] . ')) 
    * sin(radians(`lat`))))';
}

public static function convertKMToMiles($dist)
{
    return $dist * 1.609344;
}

Теперь позвоните в контроллер

$coordinates = ['latitude' => '28.392200', 'longitude' => '77.320801'];

$rsine = Location::rsine($coordinates);

$radius = Location::convertKMToMiles(5); //convert KM to miles

$users = User::with(['location' => function ($query) use ($rsine) {
               $query->selectRaw("*, {$rsine} AS distance");
         }])->whereHas('location', function ($query) use ($radius, $rsine) {
               $query->isWithinMaxDistance($rsine, $radius);
         })->get();

Теперь вы можете напечатать это так

foreach($users as $user){
   $user->name;
   $user->location->city;
   $user->location->distance;
}
...