解决办法:我们只需要在redis里面添加坐标数据即可,添加这三个键(geo:province geo:city geo:district)
添加后的成功截图:
由于项目要用到坐标,Fastadmin看官方提供了一个接口默认地址 /api/common/init ,(可以在自己的域名后加入/api.html),然后提交了经纬度,如图:
citydata 为空;
赶紧看了接口代码
官方里面代码如下:
1 <?php 2 3 namespace appapicontroller; 4 5 use appcommoncontrollerApi; 6 use appcommonmodelArea; 7 use appcommonmodelVersion; 8 use fastRandom; 9 use thinkConfig; 10 11 /** 12 * 公共接口 13 */ 14 class Common extends Api 15 { 16 protected $noNeedLogin = ['init']; 17 protected $noNeedRight = '*'; 18 19 /** 20 * 加载初始化 21 * 22 * @param string $version 版本号 23 * @param string $lng 经度 24 * @param string $lat 纬度 25 */ 26 public function init() 27 { 28 if ($version = $this->request->request('version')) { 29 $lng = $this->request->request('lng'); 30 $lat = $this->request->request('lat'); 31 $content = [ 32 'citydata' => Area::getCityFromLngLat($lng, $lat), 33 'versiondata' => Version::check($version), 34 'uploaddata' => Config::get('upload'), 35 'coverdata' => Config::get("cover"), 36 ]; 37 $this->success('', $content); 38 } else { 39 $this->error(__('Invalid parameters')); 40 } 41 }
调用了
appcommonmodelArea 下面的getCityFromLngLat方法
官方代码如下:
1 use thinkCache; 2 use thinkModel; 3 4 /** 5 * 地区数据模型 6 */ 7 class Area extends Model 8 { 9 10 /** 11 * 根据经纬度获取当前地区信息 12 * 13 * @param string $lng 经度 14 * @param string $lat 纬度 15 * @return Area 城市信息 16 */ 17 public static function getAreaFromLngLat($lng, $lat, $level = 3) 18 { 19 $namearr = [1 => 'geo:province', 2 => 'geo:city', 3 => 'geo:district']; 20 $rangearr = [1 => 15000, 2 => 1000, 3 => 200]; 21 $geoname = isset($namearr[$level]) ? $namearr[$level] : $namearr[3]; 22 $georange = isset($rangearr[$level]) ? $rangearr[$level] : $rangearr[3]; 23 // 读取范围内的ID 24 $redis = Cache::store('redis')->handler(); 25 $georadiuslist = []; 26 if (method_exists($redis, 'georadius')) { 27 $georadiuslist = $redis->georadius($geoname, $lng, $lat, $georange, 'km', ['WITHDIST', 'COUNT' => 5, 'ASC']); 28 } 29 30 if ($georadiuslist) { 31 list($id, $distance) = $georadiuslist[0]; 32 } 33 $id = isset($id) && $id ? $id : 3; 34 return self::get($id); 35 }
然发现24行的 $redis用不了,原因有几(没安装redis,安装了密码端口被更改了,还是有就是config.php 里面的缓存模式是File,还有看切换类型要个缓存模式配置,放弃了... )
不能在分析了没时间 ,不然得加班了!
,
/****************************************************分割线******************************************************
扯远了,其实我们只需要在redis里面添加坐标数据即可 ,
由于这个项目只需要坐标用到redis就懒得切换研究了
直接原生的办法添加数据的代码只需要执行一次,也就是添加到redis里面:
代码如下:
//Db记得 use thinkDb;
数据库area这个表要有数据哦(fastadmin提供了3k多个数据{经过后期测试,详细的某个地区坐标,还是有偏差,简单来说数据有点问题,(如果要数据准,要在某个区域添加n个坐标,这样才能准确,全国这么多个市区,所以代码示例里面也就到市区)现在理解为啥要自己导入了!}),没数据可以在fastadmin的插件里面有个<开发示例>插件安装即可
1 $redis = new Redis; 2 $options = [ 3 'host' => '127.0.0.1', 4 'port' => 6379, 5 'password' => '', 6 'select' => 0, 7 'timeout' => 0, 8 'expire' => 0, 9 'persistent' => false, 10 'userprefix' => 'up:', 11 'tokenprefix' => 'tp:', 12 ]; 13 $redis->pconnect($options['host'], $options['port'], $options['timeout'], 'persistent_id_' . $options['select']); 14 // $redis->connect($options['host'], $options['port'], $options['timeout']);//非持久化 15 16 $list1 = Db::name('area')->where('level',1)->select();//Db记得 use thinkDb; 这个要有数据哦,没数据可以在fastadmin的插件里面有个<开发示例>插件安装即可 17 foreach ($list1 as $key => $val) { 18 // halt((float)$val['lng']); 19 $redis->geoadd('geo:province',(float)$val['lng'],(float)$val['lat'],$val['id']); 20 } 21 22 $list2 = Db::name('area')->where('level',2)->select(); 23 foreach ($list2 as $key => $val) { 24 $redis->geoadd('geo:city',(float)$val['lng'],(float)$val['lat'],$val['id']); 25 } 26 27 $list3 = Db::name('area')->where('level',3)->select(); 28 foreach ($list3 as $key => $val) { 29 $redis->geoadd('geo:district',(float)$val['lng'],(float)$val['lat'],$val['id']); 30 } 31 echo ("导入成功"."欢迎加入QQ群交流:153073132");
然后获取的时候我也稍微修改了下(更具自己项目缓存而定 个人没有用redis来作为缓存所以采用以下修改,如果用的非File可以试着获取),
修改appcommonmodelArea.php代码如下:
1 /** 2 * 根据经纬度获取当前地区信息 3 * 4 * @param string $lng 经度 5 * @param string $lat 纬度 6 * @return Area 城市信息 7 */ 8 public static function getAreaFromLngLat($lng, $lat, $level = 3) 9 { 10 11 $namearr = [1 => 'geo:province', 2 => 'geo:city', 3 => 'geo:district']; 12 $rangearr = [1 => 15000, 2 => 1000, 3 => 200]; 13 $geoname = isset($namearr[$level]) ? $namearr[$level] : $namearr[3]; 14 $georange = isset($rangearr[$level]) ? $rangearr[$level] : $rangearr[3]; 15 // 读取范围内的ID 16 // $redis = Cache::store('redis')->handler();//原来的这个我注释了 只是获取地区的时候才用这个 17 18 //添加的开始 欢迎加入QQ群交流:153073132 19 $options = [ 20 'host' => '127.0.0.1', 21 'port' => 6379, 22 'password' => '', 23 'select' => 0, 24 'timeout' => 0, 25 'expire' => 0, 26 'persistent' => false, 27 'userprefix' => 'up:', 28 'tokenprefix' => 'tp:', 29 ]; 30 $redis = new Redis; 31 $redis->pconnect($options['host'], $options['port'], $options['timeout'], 'persistent_id_' . $options['select']); 32 //添加的结束 欢迎加入QQ群交流:153073132 33 34 $georadiuslist = []; 35 if (method_exists($redis, 'georadius')) { 36 $georadiuslist = $redis->georadius($geoname, $lng, $lat, $georange, 'km', ['WITHDIST', 'COUNT' => 5, 'ASC']); 37 }else{ 38 halt('redis没有georadius'); 39 } 40 41 if ($georadiuslist) { 42 list($id, $distance) = $georadiuslist[0]; 43 } 44 $id = isset($id) && $id ? $id : 3; 45 return self::get($id); 46 }
就相当于只是加入了导入的数据,因为注释的,我没用混合模式
$redis = Cache::store('redis')->handler();//这个注释了是因为配置 缓存没去看怎么配置(略看了下,有点复杂)只是获取地区的时候才用这个 所以加入的,更具情况而定