如何在Laravel的select查询中调用自定义函数并传入当前表字段值
Laravel 查询时传入表字段值到自定义距离计算函数的解决方案
问题根源
你当前使用的calcula_distancia是PHP层面定义的函数,会在Laravel构造SQL语句的阶段直接执行,此时数据库查询尚未运行,自然无法获取到participantes表的实时字段值,传入的'participantes.latitude'只会被当作普通字符串处理,这就是你拿到字面量而非字段值的核心原因。
解决方案
方案1:在数据库层面创建自定义函数(推荐)
这种方案将计算逻辑下沉到SQL层,支持对计算结果进行排序、筛选,适合数据量较大的场景。
- 首先在你的数据库中创建同名的SQL自定义函数,以MySQL为例,执行以下语句创建函数(逻辑和你PHP中写的距离计算保持一致即可,示例为哈弗曼公式计算公里数):
DELIMITER // CREATE FUNCTION calcula_distancia(lat1 DOUBLE, lon1 DOUBLE, lat2 DOUBLE, lon2 DOUBLE) RETURNS DOUBLE DETERMINISTIC BEGIN -- 替换为你实际的距离计算逻辑 RETURN 6371 * acos( cos(radians(lat1)) * cos(radians(lat2)) * cos(radians(lon2) - radians(lon1)) + sin(radians(lat1)) * sin(radians(lat2)) ); END // DELIMITER ;
- 修改Laravel查询代码,使用
DB::raw调用SQL函数,原其他查询逻辑保持不变,仅替换select中的距离计算部分即可:
->select( // 其他原有字段保持不变 'unidades.descricao as desc_unid', // 使用参数绑定避免SQL注入风险 DB::raw('calcula_distancia(?, ?, participantes.latitude, participantes.longitude) as distancia', [$ofps[0]->latitude, $ofps[0]->longitude] ) )
方案2:查询完成后在PHP集合层面计算
如果你不想改动数据库结构,且数据量不大,可以先查出所有需要的字段,再遍历结果计算距离:
// 原有where、join、select逻辑不变,仅移除select中的距离计算部分,正常分页 $necps = DB::table('necessidades_part')->where('necessidades_part.id_part',"<>",$id_part) // 原有逻辑保持不变 ->orderBy('data','desc') ->paginate(10); // 遍历分页结果计算距离,不会破坏原有分页结构 $mf = new MinhasFuncoes(); $necps->through(function ($item) use ($mf, $ofps) { $item->distancia = $mf->calcula_distancia( $ofps[0]->latitude, $ofps[0]->longitude, $item->latitude, $item->longitude ); return $item; });
注意事项
- 方案1支持直接在SQL中对
distancia字段进行排序、where筛选,性能更好,适合大部分业务场景 - 方案2逻辑全部在PHP中维护,无需改动数据库,但如果需要对距离做筛选、排序,需要先查出全量数据再处理,数据量大时性能较差
内容的提问来源于stack exchange,提问作者Luiz Santa
相关产品推荐
相关产品推荐

