Как показать магазины с ближайшими длинными / латами с помощью функции поиска – Laravel 5 eloquent

В идеале я ищу подходящий ответ Laravel 5. Я пытаюсь создать приложение локатора магазина. Я до такой степени, что я пытаюсь сопоставить одну пару координат lat / long (рассчитанную по адресу, в который пользователь входит в поле поиска) с ближайшими (в пределах радиуса 100 км) координатами / существующими хранилищами в моей базе данных.

Пользователь вводит адрес, который преобразуется (используя геокодирование) в координаты lat и lng. Они отправляются на мою страницу статей, в которой есть список магазинов и карта google. Я использовал простой учебник по поиску области, чтобы показать свои статьи / магазины на основе их «адреса» текста. Но это, очевидно, не работает для двух координат. У меня есть таблица под названием «Статьи», которая имеет: id, address, lat, lng, website, title и т. Д.

Мне нужно что-то вроде этого или этого, но с помощью красноречивого.

Текущая модель статьи:

public function scopeSearch($query, $search){ return $query->where('address', 'LIKE', "%$search%" ); } 

Контроллер статей

  public function index(Request $request) { $query = $request->get('q'); $articles = $query ? Article::search($query)->get() : Article::all(); return view('articles.index', compact('categories'))->withArticles($articles); } 

Текущая форма / геокод:

  {!! Form::open(['method' => 'GET', 'id' => 'searchForm', 'name' => 'searchForm', 'route' => 'articles_path']) !!} {!! Form::input('search', 'q', null, ['placeholder' => 'LOCATION', 'class' => 'locationSearch', 'id' => 'searchInput'])!!} {!! Form::hidden('lat', null, ['id' => 'lat'])!!} {!! Form::hidden('lng', null, ['id' => 'lng'])!!} {!! Form::submit('MAKE ME HAPPY', array('id' => 'submitButton')) !!} {!! Form::close() !!} <script> $('#submitButton').on('click', function(event){ event.preventDefault(); var address = $('#searchInput').val(); geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'address': address }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { var lat = results[0].geometry.location.lat(); var lng = results[0].geometry.location.lng(); $('#lat').val(lat); $('#lng').val(lng); $('#searchForm').submit(); } else { alert("Geocode was not successful"); } }); }); </script> .  {!! Form::open(['method' => 'GET', 'id' => 'searchForm', 'name' => 'searchForm', 'route' => 'articles_path']) !!} {!! Form::input('search', 'q', null, ['placeholder' => 'LOCATION', 'class' => 'locationSearch', 'id' => 'searchInput'])!!} {!! Form::hidden('lat', null, ['id' => 'lat'])!!} {!! Form::hidden('lng', null, ['id' => 'lng'])!!} {!! Form::submit('MAKE ME HAPPY', array('id' => 'submitButton')) !!} {!! Form::close() !!} <script> $('#submitButton').on('click', function(event){ event.preventDefault(); var address = $('#searchInput').val(); geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'address': address }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { var lat = results[0].geometry.location.lat(); var lng = results[0].geometry.location.lng(); $('#lat').val(lat); $('#lng').val(lng); $('#searchForm').submit(); } else { alert("Geocode was not successful"); } }); }); </script> 

Я закончил этот совет . Я не знаю, является ли это «красноречивым» способом, но он работает. Я просто не уверен в «дистанции» и что там использовать.

Модель статьи:

 public static function getByDistance($lat, $lng, $distance) { $results = DB::select(DB::raw('SELECT id, ( 3959 * acos( cos( radians(' . $lat . ') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(' . $lng . ') ) + sin( radians(' . $lat .') ) * sin( radians(lat) ) ) ) AS distance FROM articles HAVING distance < ' . $distance . ' ORDER BY distance') ); return $results; } 

Контроллер статей

  public function index(Request $request) { $lat = $request->get('lat'); $lng = $request->get('lng'); $distance = 1; $query = Article::getByDistance($lat, $lng, $distance); if(empty($query)) { return view('articles.index', compact('categories')); } $ids = []; //Extract the id's foreach($query as $q) { array_push($ids, $q->id); } // Get the listings that match the returned ids $results = DB::table('articles')->whereIn( 'id', $ids)->orderBy('rating', 'DESC')->paginate(3); $articles = $results; return view('articles.index', compact('categories'))->withArticles($articles); } 

Лучшим решением является использование этой функции в качестве области действия. Как это:

Модель статьи:

 public static function scopeGetByDistance($query,$lat, $lng, $distance) { $results = DB::select(DB::raw('SELECT id, ( 3959 * acos( cos( radians(' . $lat . ') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(' . $lng . ') ) + sin( radians(' . $lat .') ) * sin( radians(lat) ) ) ) AS distance FROM articles HAVING distance < ' . $distance . ' ORDER BY distance') ); if(!empty($results)) { $ids = []; //Extract the id's foreach($results as $q) { array_push($ids, $q->id); } return $query->whereIn('id',$ids); } return $query; } 

Статьи Контроллер:

 public function index(Request $request) { $lat = $request->get('lat'); $lng = $request->get('lng'); $distance = 1; $articles= Article::scope1()->scope2()->scope3()->GetByDistance($lat, $lng, $distance); return $articles; }