基于日期选择筛选可用时段的Livewire实现方案咨询
解决方案
你的思路完全正确,不需要额外创建pivot表,现有Schedules和Timeslots的表结构已经能满足需求。下面是具体的实现步骤:
1. 模型关联配置
先在Schedule和Timeslot模型中建立关联,让查询更简洁:
Schedule.php
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Schedule extends Model { public function timeslot() { return $this->belongsTo(Timeslot::class); } }
Timeslot.php
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Timeslot extends Model { public function schedules() { return $this->hasMany(Schedule::class); } }
2. Livewire组件实现可用时段查询
在updatedSelectedScheduledAt方法中,通过统计当日各时段的预约数,筛选出未达上限的时段:
public $selectedScheduledAt = NULL; public $timeslots = NULL; public function updatedSelectedScheduledAt($scheduled_at) { // 统计当日每个时段的预约数量 $slotBookings = Schedule::whereDate('scheduled_at', $scheduled_at) ->select('timeslot_id', \DB::raw('count(*) as booking_count')) ->groupBy('timeslot_id') ->pluck('booking_count', 'timeslot_id'); // 获取所有时段,筛选出预约数小于上限的 $this->timeslots = Timeslot::where(function ($query) use ($slotBookings) { // 未被预约过的时段直接保留 $query->whereNotIn('id', $slotBookings->keys()) // 已预约但未达上限的时段 ->orWhereRaw('limit > (select booking_count from (?) as bookings where bookings.timeslot_id = timeslots.id)', [$slotBookings]); })->get(); // 可选:无可用时段时清空已选时段 if ($this->timeslots->isEmpty()) { $this->slot_id = null; } }
如果数据量不大,也可以用更直观的筛选方式:
public function updatedSelectedScheduledAt($scheduled_at) { $this->timeslots = Timeslot::get()->filter(function ($timeslot) use ($scheduled_at) { $bookingCount = Schedule::whereDate('scheduled_at', $scheduled_at) ->where('timeslot_id', $timeslot->id) ->count(); return $bookingCount < $timeslot->limit; }); }
3. 优化原校验逻辑
利用模型关联简化原校验代码,提升效率:
// 替换原校验逻辑 $timeslot = Timeslot::find($this->timeslot_id); $bookingCount = $timeslot->schedules() ->whereDate('scheduled_at', $this->selectedScheduledAt) ->count(); if ($bookingCount >= $timeslot->limit) { session()->flash('callout', ['type' => 'error', 'message' => '该时段预约已满,请选择其他日期或时段!']); }
4. 视图代码小调整
修正视图中错误提示的变量名,与组件保持一致:
@error('slot_id') <span class="error">{{ $message }}</span> @enderror
内容的提问来源于stack exchange,提问作者Daniel Sonoiki
相关产品推荐
相关产品推荐

