
Lightning-fast schedule management for Laravel
A flexible, performant, and developer-friendly schedule management system with deep Laravel integration.
Installation β’ Quick Start β’ Features β’ Documentation β’ Contributing
- ποΈ Eloquent Integration - User HasMany Schedules with period-based scheduling
- β‘ Business Rules Engine - Configurable validation with Laravel integration
- β° Temporal Operations - Carbon-based date/time manipulation with timezone support
- π Smart Conflict Detection - Automatic overlap checking with customizable buffers
- π Recurring Schedules - Support for daily, weekly, monthly, and custom patterns
- π Availability Management - Intelligent time slot generation and conflict resolution
- π§© Laravel Native - Facades, service providers, events, and configuration
- π©βπ» Developer Experience - Fluent API, comprehensive testing, and clear documentation
- PHP 8.2+
- Laravel 11.0+
- Carbon 2.0+ or 3.0+
composer require laraveljutsu/zap
# Publish and run migrations
php artisan vendor:publish --tag=zap-migrations
php artisan migrate
# Publish configuration (optional)
php artisan vendor:publish --tag=zap-config
use Zap\Models\Concerns\HasSchedules;
class User extends Authenticatable
{
use HasSchedules;
// ...
}
use Zap\Facades\Zap;
$user = User::find(1);
$schedule = Zap::for($user)
->named('Doctor Appointment')
->description('Annual checkup')
->from('2025-03-15')
->addPeriod('09:00', '10:00')
->save();
// Weekly team meeting
$meeting = Zap::for($user)
->named('Team Standup')
->from('2025-01-01')
->to('2025-12-31')
->addPeriod('09:00', '09:30')
->weekly(['monday', 'wednesday', 'friday'])
->save();
$schedule = Zap::for($user)
->named('Client Meeting')
->from('2025-03-15')
->addPeriod('14:00', '16:00')
->noOverlap() // Prevent conflicts
->workingHoursOnly('09:00', '18:00') // Business hours only
->maxDuration(240) // Max 4 hours
->withMetadata([
'location' => 'Conference Room A',
'priority' => 'high'
])
->save();
// Check availability
$available = $user->isAvailableAt('2025-03-15', '14:00', '16:00');
// Get available slots
$slots = $user->getAvailableSlots(
date: '2025-03-15',
dayStart: '09:00',
dayEnd: '17:00',
slotDuration: 60
);
// Find next available slot
$nextSlot = $user->getNextAvailableSlot(
afterDate: '2025-03-15',
duration: 120,
dayStart: '09:00',
dayEnd: '17:00'
);
// Check for conflicts
$conflicts = Zap::findConflicts($schedule);
// Automatic conflict prevention
try {
$schedule = Zap::for($user)
->from('2025-03-15')
->addPeriod('14:00', '16:00')
->noOverlap()
->save();
} catch (ScheduleConflictException $e) {
$conflicts = $e->getConflictingSchedules();
}
// Get schedules for date
$todaySchedules = $user->schedulesForDate(today());
// Get schedules for range
$weekSchedules = $user->schedulesForDateRange('2025-03-11', '2025-03-17');
// Advanced queries
$schedules = Schedule::active()
->forDate('2025-03-15')
->whereHas('periods', function ($query) {
$query->whereBetween('start_time', ['09:00', '17:00']);
})
->get();
Configure Zap in config/zap.php
:
return [
'default_rules' => [
'no_overlap' => true,
'working_hours' => [
'enabled' => false,
'start' => '09:00',
'end' => '17:00',
],
'max_duration' => [
'enabled' => false,
'minutes' => 480,
],
],
'conflict_detection' => [
'enabled' => true,
'buffer_minutes' => 0,
'strict_mode' => true,
],
'cache' => [
'enabled' => true,
'ttl' => 3600,
'prefix' => 'zap_schedule_',
],
];
π Appointment Booking System
// Doctor availability
$availability = Zap::for($doctor)
->named('Available Hours')
->from('2025-03-01')->to('2025-03-31')
->addPeriod('09:00', '12:00')
->addPeriod('14:00', '17:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();
// Book appointment
$appointment = Zap::for($doctor)
->named('Patient Consultation')
->from('2025-03-15')
->addPeriod('10:00', '10:30')
->noOverlap()
->save();
π’ Meeting Room Management
// Room maintenance
$maintenance = Zap::for($room)
->named('Monthly Maintenance')
->from('2025-03-01')
->addPeriod('18:00', '20:00')
->monthly(['day_of_month' => 1])
->save();
// Book meeting room
$meeting = Zap::for($room)
->named('Board Meeting')
->from('2025-03-15')
->addPeriod('09:00', '11:00')
->noOverlap()
->withMetadata([
'organizer' => 'john@company.com',
'equipment' => ['projector', 'whiteboard']
])
->save();
π¨βπΌ Employee Shift Management
// Regular shifts
$workSchedule = Zap::for($employee)
->named('Regular Shift')
->from('2025-01-01')->to('2025-12-31')
->addPeriod('09:00', '17:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->noWeekends()
->save();
// Overtime
$overtime = Zap::for($employee)
->named('Overtime - Project Deadline')
->from('2025-03-15')
->addPeriod('18:00', '22:00')
->maxDuration(240)
->save();
// Listen to schedule events
protected $listen = [
\Zap\Events\ScheduleCreated::class => [
\App\Listeners\SendScheduleNotification::class,
],
];
// Create test schedules easily
$schedule = createScheduleFor($user, [
'name' => 'Test Meeting',
'start_date' => '2025-01-01',
'periods' => [['start_time' => '09:00', 'end_time' => '10:00']],
]);
// Custom indexes for better performance
Schema::table('schedules', function (Blueprint $table) {
$table->index(['schedulable_type', 'start_date', 'is_active']);
});
// Optimize queries
$schedules = Schedule::with(['periods', 'schedulable'])
->forDateRange('2025-03-01', '2025-03-31')
->get();
// Cache control
Cache::tags(['zap', 'schedules'])->flush();
We welcome contributions! Please see our Contributing Guidelines for details.
git clone https://github.com/laraveljutsu/zap.git
cd zap
composer install
vendor/bin/pest
Laravel Zap is open-source software licensed under the MIT License.
If you discover security vulnerabilities, please email ludo@epekta.com instead of using the issue tracker.
β‘ Made with β€οΈ by Laravel Jutsu for the Laravel community β‘
Website β’ Documentation β’ Support