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

Laravel Eloquent多whereHas关联查询实现公交线路站点顺序校验

实现方案

你可以直接把原生SQL的EXISTS校验逻辑平移到Eloquent查询中,同时关联places表直接通过slug匹配地点,完整代码如下:

use Illuminate\Support\Facades\DB;

$buses = Bus::whereHas('route', function ($query) use ($from, $to) {
    $query->whereExists(function ($startQuery) use ($from, $to) {
        $startQuery->select(DB::raw(1))
            ->from('route_locations as start_loc')
            // 关联出发地地点表匹配slug
            ->join('places as start_place', 'start_loc.place_id', '=', 'start_place.id')
            ->whereColumn('start_loc.route_id', 'routes.id')
            ->where('start_place.slug', $from)
            ->where('start_loc.end', 0)
            // 校验存在顺序更靠后的目的地站点
            ->whereExists(function ($endQuery) use ($to) {
                $endQuery->select(DB::raw(1))
                    ->from('route_locations as end_loc')
                    ->join('places as end_place', 'end_loc.place_id', '=', 'end_place.id')
                    ->whereColumn('end_loc.route_id', 'start_loc.route_id')
                    ->where('end_place.slug', $to)
                    ->where('end_loc.start', 0)
                    ->whereColumn('end_loc.order', '>', 'start_loc.order');
            });
    });
})
// 预加载关联数据,视图层可直接调用关联属性
->with(['route.locations.place'])
->get();

注意事项

order是SQL保留关键字,如果运行时报语法错误,需要将end_loc.order和start_loc.order替换为DB::raw('order')做转义。
如果需要优化查询性能,建议新增三个索引:

  • places表slug字段加唯一索引
  • route_locations表加(route_id, place_id, order)联合索引

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:15:03