使用laravel开发简易的附近动态功能
简介
公司app准备做个附近的功能,方便用户交(y)流(p),然后呢,大概目标就是点击附近,出来一列的用户动态列表,按时间地点距离排列。
思路
在网上找了一些资料,发现有三种实现方法,mysql,redis,MongoDB;mysql因为用公式来跑select,用户一多就难受了,所以采用redis来存用户的地理位置,再用redis的新命令实现计算筛选用户。
开始
redis命令解释中文命令:
- key:区域名或者空间名,我们统一用‘moment’
- longitude:经度
- latitude:纬度
- member:即为redis的key值,我们用moments表的id来代表
- key::区域名或者空间名,我们统一用‘moment’
- longitude:经度
- latitude:纬度
- radius:距离,比如附近1km内
- km:默认用千米
- option:多个返回参数用到的有:(WITHDIST->返回这个点和当前用户的位置的距离,ASC->从近到远排列)
设计
一个是mysql的表,一个是redis存放地点;利用moments表的主键id来做redis的唯一key
准备两个api:开发
- 添加两条路由
- 创建model文件
- 添加redisLbs文件
随便放到help还是什么目录就好,namespace可以找到就行
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2018/3/29 * Time: 14:26 */ namespace App\Helps\api; class redisLbs { /** @var Redis */ private $redis; public function __construct($config = array()) { $host = isset($config['host']) ? $config['host'] : '127.0.0.1'; $port = isset($config['port']) ? $config['port'] : '6379'; $redis = new \Redis(); $redis->connect($host, $port); if (env('APP_ENV') != 'local'){ $redis->auth('myRedis'); $redis ->set( "root" , "myRedis"); } $this->setRedis($redis); } public function getRedis() { return $this->redis; } public function setRedis($redis) { $this->redis = $redis; } //添加点 public function geoAdd($uin, $lon, $lat) { $redis = $this->getRedis(); $redis->geoAdd('moments', $lon, $lat, $uin); return true; } //获取点 public function geoNearFind($longitude , $latitude , $maxDistance = 0, $unit = 'km') { $redis = $this->getRedis(); $options = ['WITHDIST','ASC','WITHCOORD']; //显示距离 $list = $redis->geoRadius('moments', $longitude, $latitude , $maxDistance, $unit, $options); return $list; } }
- 创建控制器
- 逻辑代码
<?php namespace App\Http\Controllers; use App\Help\redisLbs; use App\Moment; use Illuminate\Http\Request; class NearByController extends Controller { /* * 添加新动态:1.mysql插入 2.redis插入 */ public function postMoment(Request $request,Moment $moment) { $user = $this->authenticate($request);//根据根据实际登录用户 if (!$request->input('longitude')){ return $this->failure(0,'缺少经度'); } if (!$request->input('latitude')){ return $this->failure(0,'缺少纬度'); } //依赖注入,随时用 $moment->user_id = $user->id; //根据实际登录用户 $moment->longitude = $request->input('longitude'); $moment->latitude = $request->input('latitude'); $moment->created_at = time(); $moment->updated_at = time(); if ($moment->save()){ //连接redis加点 $lbs = new redisLbs(); $result = $lbs->geoAdd($moment->id, $request->input('longitude'), $request->input('latitude')); if ($result){ return $this->success(1,'添加动态成功',$moment); } return $this->failure(0,'动态添加成功,redis同步失败'); } return $this->failure(0,'动态添加失败'); } /* * 获取附近动态 */ public function getMomentsList(Request $request) { $lbs = new redisLbs(); $result = $lbs->geoNearFind($request->input('longitude'),$request->input('latitude'),30000); //获取附近距离3w米的 /* 返回的两个坐标点,mid为76和12,距离,还有经纬度 [ "76", "1112.2630", [ "100.19999831914902", "39.999999910849162" ] ], [ "12", "2213.4033", [ "100.19999831914902", "10.100000747410967" ] ], */ $mid = $dist=[]; for($i=0;$i<count($result);$i++){ $dist[$i]['mid'] = $mid[$i] = $result[$i][0]; //点的id,也就是moment的主键 $dist[$i]['distance'] = $result[$i][1]; } $moments = Moment::where([ ['created_at','>',date('Y-m-d H:m:i',time()-1800)], ])->whereIn('id', $mid)->orderBy('created_at', 'desc')->get()->toArray(); //根据距离排序动态列表 $date = array_column($moments, 'distance'); array_multisort($date,SORT_ASC,$moments); return $this->success(1,'成功获取附近动态',$moments); } }具体的代码还需具体实现,比如用户,认证等等,这里只有相关演示代码。大体思路就是酱紫,有更好的思路
友情提示:垃圾评论一律封号...