laravel-zap for Laravel Scheduling and Availability
The missing calendar management for Laravel
At a glance
- What is it?
- Laravel Zap adds recurring availability, appointments, blocked periods, and bookable-slot queries to Laravel resource models. It fits PHP 8.5 and Laravel 12 applications that need scheduling rules without building the calendar domain from scratch.
- Who is it for?
- Laravel teams running PHP 8.5 and Laravel 12 should consider Zap when schedulable resources need recurring availability, exclusion rules, and slot lookup through Eloquent models. Projects on older framework versions, or applications that primarily need a full interactive calendar interface, should look elsewhere or account for those gaps first.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 23 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Where Laravel Zap Fits in a Laravel Application
Laravel Zap addresses the scheduling rules around bookable resources. The README names doctors, rooms, and employees as examples, and also lists appointment booking, healthcare resources, employee shifts, and shared-space booking as use cases. A resource becomes schedulable when its Laravel model uses the `HasSchedules` trait. From there, the package separates when a resource is available, when it is occupied, when it cannot be booked, and which application-specific rules govern overlap.
That separation is useful because an application can have working hours for weekdays, a blocked lunch period, and confirmed appointments without representing all of them as identical records. The documented overlap policy also differs by schedule type. Availability permits overlap, appointments and blocked periods are exclusive, and custom schedules leave the overlap rule to the application.
Zap is a domain package rather than a complete calendar front end. The available documentation focuses on PHP models, fluent schedule creation, and querying slots. It does not describe a ready-made booking page, calendar interface, notification workflow, payment flow, or external calendar synchronization. Those application concerns remain outside the documented core.
Laravel Zap's Schedule Builder and Slot Query Flow
The fluent API is the main mechanism documented by the project. Calls begin with `Zap::for($resource)`, followed by a name and a schedule type such as `availability()`, `appointment()`, `blocked()`, or a custom schedule. The builder then receives recurrence, date range, time period, metadata, and overlap-related settings before `save()` persists the schedule.
Recurrence is broad for application-defined rules. The README documents daily, weekly, odd or even weeks, biweekly, monthly, bimonthly, quarterly, semiannual, and annual schedules. It also documents ordinal weekdays such as the first Wednesday of a month and dynamic intervals such as every three weeks or every four months. Date boundaries can be expressed with `from()`, `on()`, `to()`, `between()`, or `forYear()`.
Bookable slots are queried back through the schedulable model. The quick start calls `getBookableSlots('2025-01-15', 60, 15)` for a 60-minute appointment with a 15-minute buffer, while `getNextBookableSlot()` returns the next matching slot. Based on the documented API, the model trait is the bridge between schedule definitions and application queries: rules are attached to a resource, then evaluated through that same resource instance.
The excerpt does not document the underlying database tables, SQL, timezone handling, event dispatching, or concurrency mechanism. Those implementation details should not be inferred merely from the fluent syntax.
Installing Laravel Zap and Creating the First Schedule
Laravel Zap documents PHP 8.5 or later and Laravel 12.0 or later as its requirements. Install the Composer package and publish its service provider configuration. The vendor publishing command makes the package configuration available to the Laravel application.
composer require laraveljutsu/zap
php artisan vendor:publish --provider="Zap\ZapServiceProvider"Before migrating, applications using non-integer primary keys must review the custom model support. The README warns that migrations and configuration may need changes for UUIDs or ULIDs. Once the key strategy is confirmed, create the package database structures with Artisan.
php artisan migrateThe expected result is a successful Laravel migration run. The README does not show the resulting migration output or schema, so the tables and columns should be inspected through the normal Laravel migration workflow if a project requires a specific database layout.
Next, make the Laravel model that represents a bookable resource use `HasSchedules`. This example models a doctor, but the same mechanism can represent another resource type.
use Zap\Models\Concerns\HasSchedules;
class Doctor extends Model
{
use HasSchedules;
}After adding the trait, the model exposes the documented scheduling relationship and slot-query methods.
Defining Working Hours, Lunch Blocks, and Appointments
A first real booking setup needs at least one availability rule, any periods that exclude booking, and an appointment. In the README example, a doctor has office hours from 09:00 to 12:00 and 14:00 to 17:00 on weekdays. A blocked lunch schedule runs from 12:00 to 13:00 on the same days. This directly reflects Zap's exclusive blocked-time policy.
Create the working-hours availability for the year with the facade. The schedule name identifies the rule, while `weekly()` limits it to the listed weekdays.
Zap::for($doctor)
->named('Office Hours')
->availability()
->forYear(2025)
->addPeriod('09:00', '12:00')
->addPeriod('14:00', '17:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();Add the exclusive lunch block with the same resource and year. The blocked schedule overlaps neither of the availability periods, so a reader can see how separate schedule types express distinct booking rules.
Zap::for($doctor)
->named('Lunch Break')
->blocked()
->forYear(2025)
->addPeriod('12:00', '13:00')
->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
->save();An appointment adds application data through `withMetadata()`. The documented example stores `patient_id` and `type`, which suggests that schedule metadata can connect a booking to application records without replacing the booking model.
Zap::for($doctor)
->named('Patient A - Consultation')
->appointment()
->from('2025-01-15')
->addPeriod('10:00', '11:00')
->withMetadata(['patient_id' => 1, 'type' => 'consultation'])
->save();Finally, query the resource for bookable slots. The arguments shown by the README are a date, a 60-minute duration, and a 15-minute buffer. A second method returns only the next matching slot.
$slots = $doctor->getBookableSlots('2025-01-15', 60, 15);
$nextSlot = $doctor->getNextBookableSlot('2025-01-15', 60, 15);Recurring Rules for Shifts and Resource Bookings
The recurrence API is a notable feature for shift and shared-resource domains. Weekly rules accept day lists, while `weekDays()` combines days and a period. Odd and even weeks are available, as are biweekly rules with a documented start date. Monthly schedules can select numerical days of the month, start months, and frequencies such as bimonthly, quarterly, semiannual, or annual.
$schedule->weekly(['monday', 'wednesday', 'friday'])->forYear(2025);
$schedule->monthly(['days_of_month' => [1, 15]])->forYear(2025);
$schedule->firstWednesdayOfMonth()->forYear(2025);
$schedule->lastMondayOfMonth()->forYear(2025);Ordinal weekday methods cover rules that cannot be expressed as a fixed date. `firstWednesdayOfMonth()`, `secondFridayOfMonth()`, and `lastMondayOfMonth()` are documented, with similar methods for other ordinal weekdays. Dynamic intervals go beyond common weekly and monthly cadences.
$schedule->everyThreeWeeks(['monday', 'friday'])->from('2025-01-06')->to('2025-12-31');
$schedule->everyFourMonths(['day_of_month' => 15])->forYear(2025);This breadth reduces the need to expand common recurring rules manually. It also creates a decision point. Projects must choose the recurrence that represents their actual policy rather than approximate it with daily schedules and application-side filtering. The README excerpt does not explain recurrence expansion performance for long date ranges, nor does it document timezone-sensitive behavior around midnight.
Laravel Zap Constraints, Alternatives, and Maintenance
The clearest constraint is platform compatibility. The README requires PHP 8.5 and Laravel 12.0, which excludes applications pinned to earlier major versions without another approach. The UUID and ULID warning is equally concrete: applications with non-integer primary keys may need migration and configuration changes before running `php artisan migrate`.
Zap is also the wrong tool if the primary requirement is a complete user-facing calendar. Its documented center of gravity is schedule definitions and bookable-slot calculation. A package centered on rendering calendars would take a different approach by focusing on calendar events, views, navigation, and interaction. Zap instead focuses on whether a Laravel resource can be booked, with availability, exclusive appointments, blocked periods, custom overlap rules, and model queries.
Another real limitation is booking concurrency. The documentation excerpt explains exclusive appointment overlaps, but it does not describe database transactions, locks, or a documented way to prevent two simultaneous requests from claiming the same slot. The concurrency policy should therefore be verified in the full documentation or application tests before adoption.
The repository is not archived, and the last push was on 2026-09-30. Recent releases include v1.15.7 on 2026-09-30, v1.15.6 on 2026-09-05, and v1.15.5 on 2026-06-27. That history indicates recent project changes, although upgrade cost still depends on the migrations, configuration changes, and custom model changes required by a specific application.
The repository identifies the MIT license. That permits use, modification, distribution, and sublicensing under the license's conditions, including preservation of its copyright and permission notice. This is a license summary, not legal advice.
Editorial conclusion
Laravel teams running PHP 8.5 and Laravel 12 should consider Zap when schedulable resources need recurring availability, exclusion rules, and slot lookup through Eloquent models. Projects on older framework versions, or applications that primarily need a full interactive calendar interface, should look elsewhere or account for those gaps first. Verify the primary-key requirement, especially for UUID and ULID models, then confirm that the documented availability and appointment overlap rules match the booking policy.
Frequently asked questions
What are the PHP and Laravel requirements for Laravel Zap?
The README requires PHP 8.5 or later and Laravel 12.0 or later. Applications using older major versions need to resolve the compatibility difference before installation.
Does Laravel Zap support UUID and ULID primary keys?
The README directs applications with non-integer primary keys to the custom model support documentation before migrating. It warns that migrations and configuration may need changes.
How does Laravel Zap calculate bookable appointment slots?
A schedulable model provides `getBookableSlots()` and `getNextBookableSlot()`. The documented call passes a date, duration, and buffer, allowing availability, appointments, and blocked periods to determine the returned slots.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ludoguenet-laravel-zap)Was this useful?