laravel+redis 附近的车辆 + 发布订单 + 司机抢单
路由#
Route::get('post-moment-import', [\App\Http\Controllers\IndexController::class, 'postMomentImport']);
Route::get('post-moment', [\App\Http\Controllers\IndexController::class, 'postMoment']);
Route::get('edit-moment/{moment}', [\App\Http\Controllers\IndexController::class, 'editMoment']);
Route::get('get-moments', [\App\Http\Controllers\IndexController::class, 'getMoments']);
// 发布抢单
Route::get('issue-order', [\App\Http\Controllers\IndexController::class, 'IssueOrder']);
// 抢单
Route::get('grab-single', [\App\Http\Controllers\IndexController::class, 'GrabSingle']);
Collection#
<?php
namespace App\Http\Controllers;
use App\Helps\api\redisLbs;
use App\Models\Moment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
class IndexController extends Controller
{
public function postMoment (Request $request, Moment $moment)
{
if (!$request->longitude){
return response()->json(['status' => 0, 'msg' => '缺少经度']);
}
if (!$request->latitude){
return response()->json(['status' => 0, 'msg' => '缺少纬度']);
}
//依赖注入,随时用
$moment->name = $request->name;
$moment->longitude = $request->input('longitude');
$moment->latitude = $request->input('latitude');
if ($moment->save()){
//连接redis加点
$lbs = new redisLbs();
$result = $lbs->geoAdd($moment->id, $request->input('longitude'), $request->input('latitude'));
if ($result){
return response()->json(['status' => 1, 'msg' => '添加动态成功']);
}
return response()->json(['status' => 0, 'msg' => '动态添加成功,redis同步失败']);
}
return response()->json(['status' => 0, 'msg' => '动态添加失败']);
}
public function postMomentImport ()
{
$json = '[{"name":"xxx","poi":"118.96,42.2737"}]';
$json_arr = json_decode($json, JSON_UNESCAPED_UNICODE);
foreach (collect($json_arr)->chunk(300) ?? [] as $chunk)
{
foreach ($chunk ?? [] as $arr)
{
list($longitude, $latitude) = explode(',', $arr['poi']);
$moment = Moment::create([
'name' => $arr['name'],
'longitude' => $longitude,
'latitude' => $latitude,
]);
// $lbs = new redisLbs();
// $result = $lbs->geoAdd($moment->id, $longitude, $latitude);
}
}
return response()->json(['status' => 1, 'msg' => '更新动态成功']);
}
public function editMoment (Request $request, Moment $moment)
{
if (!$request->longitude){
return response()->json(['status' => 0, 'msg' => '缺少经度']);
}
if (!$request->latitude){
return response()->json(['status' => 0, 'msg' => '缺少纬度']);
}
//依赖注入,随时用
$moment->name = $request->name;
$moment->longitude = $request->input('longitude');
$moment->latitude = $request->input('latitude');
if ($moment->save()){
//连接redis加点
$lbs = new redisLbs();
$result = $lbs->geoAdd($moment->id, $request->input('longitude'), $request->input('latitude'));
if ($result){
return response()->json(['status' => 1, 'msg' => '更新动态成功']);
}
return response()->json(['status' => 0, 'msg' => '动态更新成功,redis同步失败']);
}
return response()->json(['status' => 0, 'msg' => '动态更新失败']);
}
public function getMoments (Request $request)
{
$lbs = new redisLbs();
$result = $lbs->geoNearFind($request->longitude,$request->latitude,1000); //获取附近距离3千米的
/* 返回的两个坐标点,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'] = round($result[$i][1], 2);
}
// $moments = Moment::where([
// ['created_at','>',date('Y-m-d H:m:i',time()-1800)],
// ])->whereIn('id', $mid)->orderBy('created_at', 'desc')->get()->toArray();
$moments = Moment::whereIn('id', $mid)->orderBy('created_at', 'desc')->select('id', 'name')->get()->toArray();
// 合并数组
foreach ($dist ?? [] as $item)
{
foreach ($moments ?? [] as $k => $moment)
{
if ($item['mid'] == $moment['id'])
{
$moments[$k]['distance'] = $item['distance'];
}
}
}
// 根据distance进行排序
$datas = collect($moments)->sortBy('distance')->values()->all();
return response()->json(['status' => 1, 'msg' => '成功获取附近动态', 'data' => $datas]);
}
public function IssueOrder ()
{
$orderNum = 2000; // 发布了20个签单订单
for ($i=1; $i <= $orderNum; $i++) {
$grab_orders = "grab_orders".$i;
Redis::lpush($grab_orders, 1);
}
return response()->json(['status' => 200, 'msg' => '发布成功!']);
}
public function GrabSingle (Request $request)
{
// 用户id
$userId = rand(1, 9999);
// 抢单订单的id
$orderId = rand(1, 2000);
//对应商品库存队列
$goods = "grab_orders".$orderId;
//对应商品抢购成功用户集合 {1,3,4}
$robSuccessUser = "success_user".$orderId;
//进行判断当前用户是否在抢成功的队列里面
$result = Redis::sismember($robSuccessUser,$userId);
//如果你在这里面,就抢完了
if ($result) {
//如果抢购成功 返回状态码,进行下单
Log::info("用户:{$userId},已经抢过了,订单:{$goods}");
return response()->json(['status' => 20000, 'data' => '', 'msg' => '您已经抢购过了']);
}
//减库存,把队列里面的数据从左边 头
$count = Redis::lpop($goods);
if (!$count) {
//如果抢购成功 返回状态码,进行下单
Log::info("用户:{$userId},已经抢光了哦,订单:{$goods},手慢了");
return response()->json(['status' => 20001, 'data' => '', 'msg' => '已经抢光了哦']);
}
//把当前这个秒杀的uid存储到中奖的队列里set
$success = Redis::sadd($robSuccessUser, $userId);
if(!$success){
//已经在成功队列里了,加回库存,防止的是同个用户并发请求
Redis::lpush($goods, 1);
//如果抢购成功 返回状态码,进行下单
Log::info("用户:{$userId},已经抢购过了,订单:{$goods},无需在枪");
return response()->json(['status' => 20002, 'data' => '', 'msg' => '已经抢购过了']);
}
//如果抢购成功 返回状态码,进行下单
Log::info("用户:{$userId},抢单成功,订单:{$goods}");
return response()->json(['status' => 200, 'data' => '', 'msg' => '抢单成功']);
}
}
RedisLbs#
<?php
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 = 'm')
{
$redis = $this->getRedis();
$options = ['WITHDIST','ASC','WITHCOORD']; //显示距离
$list = $redis->geoRadius('moments', $longitude, $latitude , $maxDistance, $unit, $options);
return $list;
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: