The bookable slots feature provides availability-based scheduling that automatically respects your availability schedules and conflicts. Unlike getAvailableSlots() which generates slots within a time range, getBookableSlots() only generates slots that intersect with your defined availability periods.
| Method | Purpose | Time Range | Availability Respect |
|---|---|---|---|
getAvailableSlots() | Generate slots in time range | Fixed start/end times | Checks conflicts only |
getBookableSlots() | Generate slots from availability | Based on availability periods | Respects availability schedules |
// First, create availability schedules
$availability = Zap::for($doctor)
->named('Office Hours')
->availability()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('09:00', '12:00') // Morning session
->addPeriod('14:00', '17:00') // Afternoon session
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Get bookable slots for a specific date
$slots = $doctor->getBookableSlots(
date: '2025-01-15', // Wednesday
slotDuration: 60,
bufferMinutes: 15
);
foreach ($slots as $slot) {
if ($slot['is_available']) {
echo "Bookable: {$slot['start_time']} - {$slot['end_time']}";
}
}
// Find the next available bookable slot
$nextSlot = $doctor->getNextBookableSlot(
afterDate: '2025-01-15',
duration: 90, // 1.5 hours needed
bufferMinutes: 10
);
if ($nextSlot) {
echo "Next bookable: {$nextSlot['date']} from {$nextSlot['start_time']} to {$nextSlot['end_time']}";
}
// Create availability with multiple periods
$availability = Zap::for($stylist)
->named('Working Hours')
->availability()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('09:00', '12:00') // Morning
->addPeriod('14:00', '18:00') // Afternoon
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Get bookable slots - will only show slots within these periods
$slots = $stylist->getBookableSlots('2025-01-15', 45, 15);
// Results: 9:00-9:45, 10:00-10:45, 11:00-11:45, 2:00-2:45, 3:00-3:45, etc.
// No slots during lunch break (12:00-14:00)
// Create availability
$availability = Zap::for($doctor)
->named('Office Hours')
->availability()
->from('2025-01-15')
->addPeriod('09:00', '17:00')
->save();
// Create existing appointment
$appointment = Zap::for($doctor)
->named('Patient A - Checkup')
->appointment()
->from('2025-01-15')
->addPeriod('10:00', '11:00')
->save();
// Get bookable slots - 10:00-11:00 will be marked as unavailable
$slots = $doctor->getBookableSlots('2025-01-15', 60, 15);
foreach ($slots as $slot) {
if ($slot['is_available']) {
echo "Available: {$slot['start_time']} - {$slot['end_time']}";
} else {
echo "Blocked: {$slot['start_time']} - {$slot['end_time']}";
}
}
// Create weekly recurring availability
$availability = Zap::for($trainer)
->named('Gym Sessions')
->availability()
->from('2025-01-01')
->addPeriod('06:00', '09:00') // Morning sessions
->addPeriod('18:00', '21:00') // Evening sessions
->weekly(['monday', 'wednesday', 'friday'])
->save();
// Get slots for different days
$mondaySlots = $trainer->getBookableSlots('2025-01-06', 60); // Monday - has slots
$tuesdaySlots = $trainer->getBookableSlots('2025-01-07', 60); // Tuesday - no slots
$wednesdaySlots = $trainer->getBookableSlots('2025-01-08', 60); // Wednesday - has slots
echo count($mondaySlots); // > 0
echo count($tuesdaySlots); // 0
echo count($wednesdaySlots); // > 0
// Doctor's availability
$availability = Zap::for($doctor)
->named('Dr. Smith - Office Hours')
->availability()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('09:00', '12:00')
->addPeriod('14:00', '17:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Lunch break
$lunchBreak = Zap::for($doctor)
->named('Lunch Break')
->blocked()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('12:00', '13:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Get bookable consultation slots
$consultationSlots = $doctor->getBookableSlots('2025-01-15', 30, 10);
// Only shows slots within office hours, excludes lunch break
foreach ($consultationSlots as $slot) {
if ($slot['is_available']) {
echo "Available consultation: {$slot['start_time']} - {$slot['end_time']}";
}
}
// Hair stylist availability
$availability = Zap::for($stylist)
->named('Working Hours')
->availability()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('09:00', '18:00')
->weekly(['tuesday', 'wednesday', 'thursday', 'friday', 'saturday'])
->save();
// Different service types with different durations and buffers
$haircutSlots = $stylist->getBookableSlots('2025-01-15', 45, 15); // 45min + 15min cleanup
$coloringSlots = $stylist->getBookableSlots('2025-01-15', 120, 30); // 2hr + 30min cleanup
// Find next available slot for any service
$nextSlot = $stylist->getNextBookableSlot(
afterDate: '2025-01-15',
duration: 60,
bufferMinutes: 20
);
// Room availability
$availability = Zap::for($room)
->named('Conference Room A')
->availability()
->from('2025-01-01')->to('2025-12-31')
->addPeriod('08:00', '18:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Check if room is bookable for specific time
$slots = $room->getBookableSlots('2025-01-15', 60, 0);
$isBookable = collect($slots)->contains(function ($slot) {
return $slot['start_time'] === '10:00' && $slot['is_available'];
});
if ($isBookable) {
// Book the room
$meeting = Zap::for($room)
->named('Team Meeting')
->appointment()
->from('2025-01-15')
->addPeriod('10:00', '11:00')
->withMetadata([
'organizer' => 'john@company.com',
'attendees' => 8
])
->save();
}
is_available before bookingpublic function getBookableSlots(
string $date,
int $slotDuration = 60,
?int $bufferMinutes = null
): array
Parameters:
$date - Date to get slots for (Y-m-d format)$slotDuration - Duration of each slot in minutes$bufferMinutes - Buffer time between slots (null = use config)Returns: Array of slot data with start_time, end_time, is_available, and buffer_minutes
public function getNextBookableSlot(
?string $afterDate = null,
int $duration = 60,
?int $bufferMinutes = null
): ?array
Parameters:
$afterDate - Start searching from this date (null = today)$duration - Duration needed in minutes$bufferMinutes - Buffer time between slots (null = use config)Returns: Next available slot data or null if none found within 30 days