Laravel8运行SQL查询获取全房间及对应预订数的实现方法
Laravel8 房间预订全量统计实现方案
问题原因
原有代码仅在查询到房间存在预订记录时,才会向结果数组追加房间名和计数值,没有预订记录的房间会被直接跳过,因此会丢失预订数为0的房间数据;同时原有代码还存在循环内重复查询数据库的性能问题、循环变量名不匹配的语法问题。
最优实现(推荐)
使用Laravel Eloquent内置的withCount方法实现,仅需2条SQL即可完成全量统计,无性能问题,且自动返回无预订房间的0计数结果。
- 首先在
app/Models/Room.php模型中定义房间和预订的一对多关联:
// 放在Room模型类内部 public function bookings() { return $this->hasMany(Booking::class, 'room_id', 'id'); }
- 控制器index方法改写为如下代码:
public function index() { // 一次性查询所有房间及对应预订总数 $rooms = Room::withCount('bookings')->get(); // 直接提取字段生成目标数组 $lebal = $rooms->pluck('name')->toArray(); $data = $rooms->pluck('bookings_count')->toArray(); return view('web.dashboard', compact('lebal', 'data')); }
运行后返回的结果完全符合预期:
- 房间名数组:
["Meeting Room","Office Rooms","Single room"] - 预订计数数组:
[1,0,1]
原有循环逻辑修正版(不推荐,性能差)
如果要保留原有循环查询的写法,可修正为如下形式,同样能得到正确结果,但房间数量较多时会产生大量SQL查询,性能较差:
public function index() { $rooms = Room::get(); $lebal = []; $data = []; foreach($rooms as $room){ // 直接统计当前房间预订数,无记录则返回0 $bookingCount = Booking::where('room_id', $room->id)->count(); $lebal[] = $room->name; $data[] = $bookingCount; } return view('web.dashboard', compact('lebal', 'data')); }
注意:该写法会产生N+1查询问题,房间数量较多时会严重影响接口性能,非特殊情况不建议使用
内容的提问来源于stack exchange,提问作者zubair syslab
相关产品推荐
相关产品推荐

