where(['status' => 1])->pluck('city_id'); $res = Area::query()->with('markets')->whereIn('id',$cityIds)->get(); foreach ($res as &$v){ if(!empty($lng) && !empty($lat)) { $v->distance_num = $this->getDistance($v->lng, $v->lat, $lng, $lat); $v->distance = $v->distance_num . ' km'; } else { $v->distance_num = 0; $v->distance = ''; } foreach ($v->markets as &$m) { if(!empty($lng) && !empty($lat)){ $m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat); $m->distance = $m->distance_num.' km'; }else{ $m->distance_num = 0; $m->distance = ''; } } } $res = collect($res->toArray())->sortBy(function ($area, $key) { return $area['distance_num']; }); $res = collect($res->all())->map(function ($area, $key) { $markets = collect($area['markets'])->sortBy('distance_num'); $area['markets'] = $markets->values()->all(); return $area; }); return $res->all(); } public function searchMarket($keywords,$lng,$lat,$cityId = 2163) { $res = Market::query()->where([ ['name','like','%'.$keywords.'%'], ['city_id','=',$cityId] ]) ->get(); foreach ($res as &$m){ if(!empty($lng) && !empty($lat)){ $m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat); $m->distance = $m->distance_num.' km'; }else{ $m->distance_num = 0; $m->distance = ''; } } $res = collect($res)->sortBy('distance_num'); return $res->values()->all(); } public function getNearestMarket($lng,$lat) { $markets = Market::query()->where(['status' => 1])->get()->toArray(); $result = []; $distinctMin = 0; foreach ($markets as &$market){ $distinct = $this->getDistance($lng,$lat,$market['lng'],$market['lat'],1); $market['distinct'] = round(($distinct/1000),2).' km'; if($distinct < $distinctMin || $distinctMin === 0) { $distinctMin = $distinct; $result = $market; } } return $result; } /** * @param $lng1 * @param $lat1 * @param $lng2 * @param $lat2 * @param int $unit 单位 1:米 2:公里 * @param int $decimal 精度 保留小数位数 * @return false|float */ public function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 2, $decimal = 2) { $EARTH_RADIUS = 6370.996; // 地球半径系数 $PI = 3.1415926535898; $radLat1 = $lat1 * $PI / 180.0; $radLat2 = $lat2 * $PI / 180.0; $radLng1 = $lng1 * $PI / 180.0; $radLng2 = $lng2 * $PI / 180.0; $a = $radLat1 - $radLat2; $b = $radLng1 - $radLng2; $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))); $distance = $distance * $EARTH_RADIUS * 1000; if ($unit === 2) { $distance /= 1000; } return round($distance, $decimal); } //获取服务站信息 function getMarketsInfo() { return Market::where('status',1)->get(); } //获取骑行距离 public function getDistanceByTencent($lng1, $lat1, $lng2, $lat2) { $url = 'https://apis.map.qq.com/ws/distance/v1/matrix/?mode='; /** * $tyep driving 驾车 walking 步行 bicycling 骑行 transit 公交 */ $type = 'bicycling'; $key = config('map.tencent'); $client = new Client([ // Base URI is used with relative requests 'base_uri' => 'https://apis.map.qq.com/', // You can set any number of default request options. 'timeout' => 2.0, ]); $response = $client->request('GET', $url.$type.'&from='.$lat1.','.$lng1.'&to='.$lat2.','.$lng2.'&output=json&key='.$key); $response = $response->getBody()->getContents(); $resultArr = json_decode($response,true); if($resultArr['status'] > 0) { throw new ErrorCodeException(ErrorCode::LOCATION_ERROR,$resultArr['message']); } $distance = $resultArr['result']['rows'][0]['elements'][0]['distance']; return $distance; } /** * 根据关键词进行地址提示 * 返回地址数据 * @param $keyword * @param string $marketId * @param int $page * @param int $pageSize * @return string * @throws GuzzleException */ public function placeSuggestion($keyword, $marketId = '', $page = 1, $pageSize = 10) { $apiPath = 'https://apis.map.qq.com/ws/place/v1/suggestion'; $queryString = 'page_index='.urlencode($page).'&page_size='.urlencode($pageSize).'&policy=1&keyword='.urlencode($keyword).'&key='.config('map.tencent'); // 获取当前市场所在城市 if ($marketId) { $cityId = Market::query()->where(['id' => $marketId])->value('city_id'); $cityName = Area::query()->where(['id' => $cityId])->value('name'); if ($cityName) { $queryString .= '®ion='.urlencode($cityName); } } $client = ApplicationContext::getContainer()->get(ClientFactory::class)->create(); $response = $client->request('GET', $apiPath.'?'.$queryString); $res = $response->getBody()->getContents(); $res = json_decode($res, true); if ($res['status'] != 0) { throw new ErrorCodeException($res['status'], $res['message']); } return $res; } }