You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel RawQuery中使用用户表radius字段实现动态半径坐标搜索

问题描述

之前通过ENV常量定义固定50km半径,查找特定坐标范围内的用户。现在希望调整逻辑:使用用户自身设定的radius字段作为判断依据,若该字段为NULL则默认采用50km,筛选出处于给定坐标自身设定半径范围内的用户。

现有查询代码:

User::selectRaw('*, (6371 * acos (cos ( radians('.$lat.') ) * cos( radians( addressLat ) ) * cos( radians( addressLong ) - radians('.$lng.') ) + sin ( radians('.$lat.') ) * sin( radians( addressLat ) ))) AS distance')
    ->orderBy('distance')
    ->having('distance', '<', $radius)
    ->whereNotNull('phone_number')
    ->where('should_receive_quotes', '!=', '0')
    ->get();

当前变量定义:

$radius = env('RADIUS',50);

相关表结构:

用户表

idlatlngradius
151.500836-1.15905880
251.164490-0.466919NULL
352.39103-2.91020NULL

报价表

idlatlng
151.267715-0.214233

预期结果:针对报价ID1,返回用户1和2。用户1在自身设定的80km范围内,用户2使用默认50km且在范围内;用户3因超出默认50km范围,不返回。

解决方案

可以实现该需求,核心是用COALESCE函数处理用户的radius字段,同时修复原代码的SQL注入风险,修改后的查询逻辑如下:

$defaultRadius = env('RADIUS', 50);

$users = User::selectRaw('
    *, 
    (6371 * acos (
        cos(radians(?)) * cos(radians(addressLat)) * cos(radians(addressLong) - radians(?)) + 
        sin(radians(?)) * sin(radians(addressLat))
    )) AS distance,
    COALESCE(radius, ?) AS effective_radius
', [$lat, $lng, $lat, $defaultRadius])
    ->orderBy('distance')
    ->havingRaw('distance < effective_radius')
    ->whereNotNull('phone_number')
    ->where('should_receive_quotes', '!=', '0')
    ->get();

关键说明:

  • COALESCE函数:COALESCE(radius, ?)会优先取用户表的radius值,若为NULL则使用传入的默认50km,将结果命名为effective_radius作为每个用户的判断半径。
  • 参数绑定:将$lat、$lng、$defaultRadius作为参数传入selectRaw,避免直接拼接字符串导致的SQL注入风险。
  • 条件调整:把原固定的$radius判断改为distance < effective_radius,让每个用户都使用自身的有效半径进行范围校验。

该代码会按照预期返回用户1和2,满足需求。

内容的提问来源于stack exchange,提问作者user26547113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 10:23:24