Laravel 7.4按医生分组获取当日患者预约的实现方案咨询
解决方案:Laravel按医生分组归集当日预约
问题根源
你之前的代码存在几个关键错误:
- JOIN语句语法错误:
join('users.id', '=', 'doctor_details.user_id')写法错误,JOIN的第一个参数应为表名而非字段,正确格式是join('users', 'users.id', '=', 'doctor_details.user_id')。 - 循环索引越界:
$i <= count($var)会导致访问超出数组长度的索引,应该改为$i < count($var)。 - 未关联当前医生:循环内的预约查询没有过滤当前医生的ID,导致所有医生都拿到了全部当日预约,而非自己的。
- N+1查询性能问题:循环内逐次查询数据库会大幅降低性能,不符合Laravel最佳实践。
推荐方案:使用Eloquent关联+预加载(最优解)
利用Laravel的Eloquent关联和预加载功能,一次性查询出所有有当日预约的医生及其预约列表,避免重复查询和数据冗余。
1. 定义模型关联
首先在对应的模型中建立关联关系:
DoctorDetail 模型:
class DoctorDetail extends Model { // 关联到用户表(医生的基础信息存在users表) public function user() { return $this->belongsTo(User::class, 'user_id'); } // 关联到医生的所有预约(通过user_id匹配预约表的doctor_id) public function appointments() { return $this->hasMany(PatientAppointment::class, 'doctor_id', 'user_id'); } }
PatientAppointment 模型(可选,用于反向关联):
class PatientAppointment extends Model { // 关联到医生用户 public function doctor() { return $this->belongsTo(User::class, 'doctor_id'); } }
2. 控制器查询逻辑
在控制器中通过预加载筛选当日有预约的医生,并归集其预约:
use Carbon\Carbon; use App\Models\DoctorDetail; public function getDoctorAppointments() { $today = Carbon::today(); // 预加载当日预约,同时只返回有当日预约的医生 $doctorsWithAppointments = DoctorDetail::with(['appointments' => function ($query) use ($today) { $query->whereDate('date', $today); }]) ->whereHas('appointments', function ($query) use ($today) { $query->whereDate('date', $today); }) ->get(); return view('your-blade-view', compact('doctorsWithAppointments')); }
3. Blade模板渲染
在Blade中循环渲染医生信息及其对应的当日预约:
@foreach($doctorsWithAppointments as $doctorDetail) <div class="doctor-card"> <h3>医生:{{ $doctorDetail->user->name }}</h3> <p>医生信息:{{ $doctorDetail->your_detail_field }}</p> <!-- 替换为doctor_details表的实际字段 --> <h4>今日预约列表:</h4> <ul> @foreach($doctorDetail->appointments as $appointment) <li> 患者ID:{{ $appointment->user_id }} | 时间:{{ $appointment->start_time }} - {{ $appointment->end_time }} </li> @endforeach </ul> </div> @endforeach
备选方案:使用查询构建器分组
如果不想依赖模型关联,也可以直接通过查询构建器分组查询:
use Carbon\Carbon; use App\Models\PatientAppointment; public function getDoctorAppointments() { $todayAppointments = PatientAppointment::whereDate('date', Carbon::today()) ->with('doctor.doctorDetail') // 预加载医生用户和医生详情 ->get() ->groupBy('doctor_id'); return view('your-blade-view', compact('todayAppointments')); }
对应的Blade渲染:
@foreach($todayAppointments as $doctorId => $appointments) @php $doctor = $appointments->first()->doctor; $doctorDetail = $doctor->doctorDetail; @endphp <div class="doctor-card"> <h3>医生:{{ $doctor->name }}</h3> <p>医生信息:{{ $doctorDetail->your_detail_field }}</p> <h4>今日预约列表:</h4> <ul> @foreach($appointments as $appointment) <li> 患者ID:{{ $appointment->user_id }} | 时间:{{ $appointment->start_time }} - {{ $appointment->end_time }} </li> @endforeach </ul> </div> @endforeach
内容的提问来源于stack exchange,提问作者Shubham Sahu
相关产品推荐
相关产品推荐

