多模型关联场景下如何通过多URL参数查询对应酒店房间数据?
正确的查询实现方案
你需要在查询房间时,逐层向上校验所属酒店、城市、国家的标识,避免同名slug导致数据查询错误,以下是两种常用的实现方式:
方式1:Eloquent 关联约束写法(推荐,符合ORM使用规范)
前提是你已经在模型中定义好了对应的关联关系:Room属于Hotel、Hotel属于City、City属于Country
$rooms = Room::whereHas('hotel', function ($query) use ($hotel, $city, $country) { $query->where('slug', $hotel) ->whereHas('city', function ($cityQuery) use ($city, $country) { $cityQuery->where('slug', $city) ->whereHas('country', function ($countryQuery) use ($country) { $countryQuery->where('slug', $country); }); }); })->get();
这种写法会自动校验层级关系,只会返回属于指定国家、城市、对应酒店的房间。
方式2:Join 联表查询写法(性能更高,适合大数据量场景)
$rooms = Room::select('rooms.*') ->join('hotels', 'rooms.hotel_id', '=', 'hotels.id') ->join('cities', 'hotels.city_id', '=', 'cities.id') ->join('countries', 'cities.country_id', '=', 'countries.id') ->where('hotels.slug', $hotel) ->where('cities.slug', $city) ->where('countries.slug', $country) ->get();
额外优化建议
- 给各表的
slug字段和父级外键加联合索引,比如hotels表加(city_id, slug)联合索引,cities表加(country_id, slug)联合索引,可大幅提升查询性能 - Laravel 8及以上版本可直接使用嵌套路由模型绑定,写法更简洁,框架会自动完成层级校验:
// 路由定义 Route::get('/last-minute/{country:slug}/{city:slug}/{hotel:slug}', function (Country $country, City $city, Hotel $hotel) { return $hotel->rooms; });
内容的提问来源于stack exchange,提问作者Wouter
相关产品推荐
相关产品推荐

