PHPackages                             laraveljutsu/zap - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. laraveljutsu/zap

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

laraveljutsu/zap
================

A flexible, performant, and developer-friendly schedule management system for Laravel

v1.14.0(2mo ago)1.4k69.1k—2.1%101MITPHPPHP &gt;=8.2 &lt;8.6CI failing

Since Jun 8Pushed 1mo ago17 watchersCompare

[ Source](https://github.com/ludoguenet/laravel-zap)[ Packagist](https://packagist.org/packages/laraveljutsu/zap)[ RSS](/packages/laraveljutsu-zap/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (4)Versions (22)Used By (0)

[![Zap Logo](art/logo.png?v=2)](art/logo.png?v=2)**Flexible schedule management for modern Laravel applications**

[![PHP Version](https://camo.githubusercontent.com/641a3f14bc91cfef175ec7fabb9a1a15b002dc0ad5069341e55fe55143a89a94/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d254532253839254134382e352d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870)](https://www.php.net/)[![Laravel Version](https://camo.githubusercontent.com/0964805f72ab5ad1c4cb61b975085625f9bf6b9b59d5ea90055059bcdf76bd79/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d25453225383925413431332e302d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c)](https://laravel.com)[![License](https://camo.githubusercontent.com/1e7c1a654d441aa36d466ce186e442246bc6c43db01f085bfba333b4eb32feaf/687474703a2f2f706f7365722e707567782e6f72672f6c61726176656c6a757473752f7a61702f6c6963656e73653f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/laraveljutsu/zap)[![Total Downloads](https://camo.githubusercontent.com/e8c7d41b120df0ac3d49f934d81efee704da0ccc89cae376447ce2af17910917/687474703a2f2f706f7365722e707567782e6f72672f6c61726176656c6a757473752f7a61702f646f776e6c6f6164733f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/laraveljutsu/zap)[![Why PHP](https://camo.githubusercontent.com/6a4e06cb04261bd5090fa9b3e75f55962ab9b1083a15bf25fcadad6b7df2fb27/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5768795f5048502d696e5f323032362d3741383645383f7374796c653d666f722d7468652d6261646765266c6162656c436f6c6f723d313831383162)](https://whyphp.dev)

[Website](https://ludovicguenet.dev) • [Documentation](https://laravel-zap.com) • [Support](mailto:ludo@epekta.com)

---

Table of contents
-----------------

[](#table-of-contents)

- [What is Zap?](#-what-is-zap)
- [Installation](#-installation)
- [Core concepts](#-core-concepts)
- [Quick start](#-quick-start)
- [Schedule patterns](#-schedule-patterns)
- [Query &amp; availability](#-query--check-availability)
- [Real-world examples](#-real-world-examples)
- [Configuration](#%EF%B8%8F-configuration)
- [Advanced](#-advanced-features)
- [AI agent support](#-ai-agent-support)
- [Contributing](#-contributing)

---

🎯 What is Zap?
--------------

[](#-what-is-zap)

Zap is a calendar and scheduling package for Laravel. Define **availabilities**, **appointments**, **blocked times**, and **custom schedules** for any resource (doctors, rooms, employees, etc.).

**Use cases:** appointment booking, healthcare resources, employee shifts, shared space booking.

---

📦 Installation
--------------

[](#-installation)

**Requirements:** PHP ≥8.5 • Laravel ≥13.0

```
composer require laraveljutsu/zap
php artisan vendor:publish --provider="Zap\ZapServiceProvider"
```

**UUIDs/ULIDs:** If your app uses non-integer primary keys, read [Custom model support](#custom-model-support) *before* migrating. You may need to change migrations and config.

```
php artisan migrate
```

**Make a model schedulable:** add the `HasSchedules` trait.

```
use Zap\Models\Concerns\HasSchedules;

class Doctor extends Model
{
    use HasSchedules;
}
```

---

🧩 Core concepts
---------------

[](#-core-concepts)

TypePurposeOverlaps**Availability**When a resource can be bookedAllowed**Appointment**Bookings / scheduled eventsExclusive**Blocked**When booking is forbiddenExclusive**Custom**Your rules (overlap, etc.)You define---

🚀 Quick start
-------------

[](#-quick-start)

```
use Zap\Facades\Zap;

// 1. Working hours
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();

// 2. Block lunch
Zap::for($doctor)
    ->named('Lunch Break')
    ->blocked()
    ->forYear(2025)
    ->addPeriod('12:00', '13:00')
    ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
    ->save();

// 3. Create an appointment
Zap::for($doctor)
    ->named('Patient A - Consultation')
    ->appointment()
    ->from('2025-01-15')
    ->addPeriod('10:00', '11:00')
    ->withMetadata(['patient_id' => 1, 'type' => 'consultation'])
    ->save();

// 4. Get bookable slots (60 min, 15 min buffer)
$slots = $doctor->getBookableSlots('2025-01-15', 60, 15);

// 5. Next available slot
$nextSlot = $doctor->getNextBookableSlot('2025-01-15', 60, 15);
```

> 💡 Use the `zap()` helper instead of the facade when you prefer: `zap()->for($doctor)->...`

---

📅 Schedule patterns
-------------------

[](#-schedule-patterns)

### Recurrence at a glance

[](#recurrence-at-a-glance)

PatternMethod / exampleDaily`daily()`Weekly (days)`weekly(['monday', 'friday'])`Weekly + period`weekDays(['monday', 'friday'], '09:00', '17:00')`Odd/even weeks`weeklyOdd()`, `weeklyEven()` (+ `weekOddDays` / `weekEvenDays`)Bi-weekly`biweekly(['tuesday'], $startsOn?)`Monthly (dates)`monthly(['days_of_month' => [1, 15]])`Bi-monthly / quarter / semi / annual`bimonthly()`, `quarterly()`, `semiannually()`, `annually()` + config**Ordinal weekday**`firstWednesdayOfMonth()`, `secondFridayOfMonth()`, `lastMondayOfMonth()`Every N weeks`everyThreeWeeks()`, … `everyFiftyTwoWeeks()`Every N months`everyFourMonths()`, … `everyElevenMonths()`### Recurrence examples

[](#recurrence-examples)

**Daily &amp; weekly**

```
$schedule->daily()->from('2025-01-01')->to('2025-12-31');
$schedule->weekly(['monday', 'wednesday', 'friday'])->forYear(2025);
$schedule->weekDays(['monday', 'wednesday', 'friday'], '09:00', '17:00')->forYear(2025);
$schedule->weeklyOdd(['monday', 'wednesday', 'friday'])->forYear(2025);
$schedule->weeklyEven(['monday', 'wednesday', 'friday'])->forYear(2025);
$schedule->biweekly(['tuesday', 'thursday'], '2025-01-07')->from('2025-01-07')->to('2025-03-31');
```

**Monthly (by day of month)**

```
$schedule->monthly(['days_of_month' => [1, 15]])->forYear(2025);
$schedule->bimonthly(['days_of_month' => [5, 20], 'start_month' => 2])->from('2025-01-05')->to('2025-06-30');
$schedule->quarterly(['days_of_month' => [7, 21], 'start_month' => 2])->from('2025-02-15')->to('2025-11-15');
$schedule->semiannually(['days_of_month' => [10], 'start_month' => 3])->from('2025-03-10')->to('2025-12-10');
$schedule->annually(['days_of_month' => [1, 15], 'start_month' => 4])->from('2025-04-01')->to('2026-04-01');
```

**Monthly ordinal weekday** (1st, 2nd, 3rd, 4th, or last weekday of the month)

```
$schedule->firstWednesdayOfMonth()->forYear(2025);   // Every 1st Wednesday
$schedule->secondFridayOfMonth()->forYear(2025);     // Every 2nd Friday
$schedule->lastMondayOfMonth()->forYear(2025);      // Every last Monday
// Also: thirdTuesdayOfMonth(), fourthSaturdayOfMonth(), lastSundayOfMonth(), etc.
```

**Dynamic intervals**

```
$schedule->everyThreeWeeks(['monday', 'friday'])->from('2025-01-06')->to('2025-12-31');
$schedule->everyFourWeeks(['tuesday'], '2025-01-06')->from('2025-01-13');
$schedule->everyFourMonths(['day_of_month' => 15])->forYear(2025);
$schedule->everyFiveMonths(['days_of_month' => [1, 15], 'start_month' => 2])->forYear(2025);
```

### Date ranges

[](#date-ranges)

```
$schedule->from('2025-01-15');                           // Start
$schedule->on('2025-01-15');                             // Alias for from()
$schedule->from('2025-01-01')->to('2025-12-31');        // Range
$schedule->between('2025-01-01', '2025-12-31');          // Same
$schedule->forYear(2025);                                // Full year
```

### Time periods

[](#time-periods)

```
$schedule->addPeriod('09:00', '17:00');
$schedule->addPeriod('09:00', '12:00');
$schedule->addPeriod('14:00', '17:00');
```

---

🔍 Query &amp; check availability
--------------------------------

[](#-query--check-availability)

NeedMethodAny bookable slot today?`$model->isBookableAt('2025-01-15', 60)`Time range bookable?`$model->isBookableAtTime('2025-01-15', '09:00', '09:30')`Time range bookable (custom slot)?`$model->isBookableAtTime('2025-01-15', '09:30', '10:00', null, 30)`List bookable slots`$model->getBookableSlots('2025-01-15', 60, 15)`Next bookable slot`$model->getNextBookableSlot('2025-01-15', 60, 15)`Conflicts for a schedule`Zap::findConflicts($schedule)` / `Zap::hasConflicts($schedule)`Schedules on a date`$model->schedulesForDate('2025-01-15')->get()`Schedules in range`$model->schedulesForDateRange('2025-01-01', '2025-01-31')->get()`By type`$model->appointmentSchedules()`, `availabilitySchedules()`, `blockedSchedules()`Schedule type checks`$schedule->isAvailability()`, `isAppointment()`, `isBlocked()`> ⚠️ `isAvailableAt()` is deprecated. Prefer `isBookableAt()`, `isBookableAtTime()`, and `getBookableSlots()`.

---

💼 Real-world examples
---------------------

[](#-real-world-examples)

### Doctor

[](#doctor)

```
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();

Zap::for($doctor)->named('Lunch Break')->blocked()->forYear(2025)
    ->addPeriod('12:00', '13:00')
    ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])->save();

Zap::for($doctor)->named('Patient A - Checkup')->appointment()
    ->from('2025-01-15')->addPeriod('10:00', '11:00')->withMetadata(['patient_id' => 1])->save();

$slots = $doctor->getBookableSlots('2025-01-15', 60, 15);
```

### Meeting room

[](#meeting-room)

```
Zap::for($room)->named('Conference Room A')->availability()
    ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '08:00', '18:00')
    ->forYear(2025)->save();

Zap::for($room)->named('Board Meeting')->appointment()
    ->from('2025-03-15')->addPeriod('09:00', '11:00')
    ->withMetadata(['organizer' => 'john@company.com'])->save();
```

### Employee (with vacation)

[](#employee-with-vacation)

```
Zap::for($employee)->named('Regular Shift')->availability()
    ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '09:00', '17:00')
    ->forYear(2025)->save();

Zap::for($employee)->named('Vacation Leave')->blocked()
    ->between('2025-06-01', '2025-06-15')->addPeriod('00:00', '23:59')->save();
```

---

⚙️ Configuration
----------------

[](#️-configuration)

Publish assets:

```
php artisan vendor:publish --tag=zap-migrations
php artisan vendor:publish --tag=zap-config
```

Important keys in `config/zap.php`: `time_slots.buffer_minutes`, `default_rules.no_overlap`, `conflict_detection`, `validation`.

---

🛡️ Advanced features
--------------------

[](#️-advanced-features)

**Custom schedules &amp; rules**

```
Zap::for($user)->named('Custom Event')->custom()
    ->from('2025-01-15')->addPeriod('15:00', '16:00')->noOverlap()->save();
```

**Metadata**

```
->withMetadata(['patient_id' => 1, 'type' => 'consultation', 'notes' => 'Follow-up'])
```

**Validation rules:** `noOverlap()`, `allowOverlap()`, `workingHoursOnly('09:00', '17:00')`, `maxDuration(120)`, `noWeekends()`.

### Custom model support (UUIDs)

[](#custom-model-support-uuids)

If your app uses **UUIDs/ULIDs** for primary keys:

1. **Models** — Extend `Zap\Models\Schedule` and `Zap\Models\SchedulePeriod`, add Laravel’s `HasUuids` trait. Add `HasUuids` to your schedulable model (e.g. `Doctor`) as well.
2. **Config** — In `config/zap.php`, set `models.schedule` and `models.schedule_period` to your extended classes.
3. **Migrations** — After publishing, change `id()` to `uuid('id')->primary()`, `morphs('schedulable')` to `uuidMorphs('schedulable')`, and `foreignId('schedule_id')` to `foreignUuid('schedule_id')` in the schedules and schedule\_periods tables.

Do this *before* running migrations.

---

🧠 AI agent support
------------------

[](#-ai-agent-support)

Zap provides [Laravel Boost](https://laravel.com/ai/boost) 2.0 skills. With Boost installed, agents get accurate knowledge of the API.

SkillContents`zap-schedules`Types, builder API, validation, conflict detection`zap-availability`Bookable slots, availability checks, querying`zap-recurrence`All recurrence patterns (daily, weekly, odd/even, monthly, ordinal weekday, dynamic)No extra configuration.

---

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome. Use PSR-12 and add tests.

```
git clone https://github.com/ludoguenet/laravel-zap.git
cd laravel-zap
composer install
composer pest
```

---

📄 License
---------

[](#-license)

[MIT License](LICENSE).

🔒 Security
----------

[](#-security)

Report issues to **** (not the public issue tracker).

---

**Made with 💛 by [Ludovic Guénet](https://www.ludovicguenet.dev) for the Laravel community**

###  Health Score

62

—

FairBetter than 99% of packages

Maintenance87

Actively maintained with recent releases

Popularity58

Moderate usage in the ecosystem

Community28

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 56.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~13 days

Total

21

Last Release

84d ago

PHP version history (2 changes)v1.0.0PHP ^8.2

v1.9.1PHP &gt;=8.2 &lt;8.6

### Community

Maintainers

![](https://www.gravatar.com/avatar/3f1ac1a4b7fdf5d9283574fc60d79c986b1f2baf67b248a65f988a681dd470a6?d=identicon)[ludoguenet](/maintainers/ludoguenet)

---

Top Contributors

[![ludoguenet](https://avatars.githubusercontent.com/u/36139526?v=4)](https://github.com/ludoguenet "ludoguenet (88 commits)")[![SonnySha](https://avatars.githubusercontent.com/u/39993743?v=4)](https://github.com/SonnySha "SonnySha (15 commits)")[![nick-potts](https://avatars.githubusercontent.com/u/1109914?v=4)](https://github.com/nick-potts "nick-potts (12 commits)")[![Sagmedjo](https://avatars.githubusercontent.com/u/46325585?v=4)](https://github.com/Sagmedjo "Sagmedjo (12 commits)")[![fabpl](https://avatars.githubusercontent.com/u/6574025?v=4)](https://github.com/fabpl "fabpl (6 commits)")[![angelej](https://avatars.githubusercontent.com/u/131715596?v=4)](https://github.com/angelej "angelej (4 commits)")[![falestra](https://avatars.githubusercontent.com/u/12063138?v=4)](https://github.com/falestra "falestra (4 commits)")[![gmlo89](https://avatars.githubusercontent.com/u/874420?v=4)](https://github.com/gmlo89 "gmlo89 (3 commits)")[![olivermbs](https://avatars.githubusercontent.com/u/37539998?v=4)](https://github.com/olivermbs "olivermbs (3 commits)")[![rajabilal555](https://avatars.githubusercontent.com/u/15360941?v=4)](https://github.com/rajabilal555 "rajabilal555 (3 commits)")[![raphaelstolt](https://avatars.githubusercontent.com/u/48225?v=4)](https://github.com/raphaelstolt "raphaelstolt (1 commits)")[![deshack](https://avatars.githubusercontent.com/u/2034213?v=4)](https://github.com/deshack "deshack (1 commits)")[![seebaermichi](https://avatars.githubusercontent.com/u/2083999?v=4)](https://github.com/seebaermichi "seebaermichi (1 commits)")[![bdj-Razik](https://avatars.githubusercontent.com/u/82386537?v=4)](https://github.com/bdj-Razik "bdj-Razik (1 commits)")[![szepeviktor](https://avatars.githubusercontent.com/u/952007?v=4)](https://github.com/szepeviktor "szepeviktor (1 commits)")

---

Tags

calendardateslaravelschedulelaravelschedulecalendarmanagementbooking

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/laraveljutsu-zap/health.svg)

```
[![Health](https://phpackages.com/badges/laraveljutsu-zap/health.svg)](https://phpackages.com/packages/laraveljutsu-zap)
```

###  Alternatives

[indeev/laravel-schedule-calendar

Laravel Schedule Calendar - a package providing developers with a concise and visual representation of scheduled tasks, enabling easy analysis of load distribution throughout the day or week for optimized task scheduling.

557.7k](/packages/indeev-laravel-schedule-calendar)[calendart/office365-adapter

Office365 Adapter for CalendArt

1213.8k](/packages/calendart-office365-adapter)[zenepay/filament-buddhist-date-picker

Laravel Filament DatePicker with Bhuddist Era plugin

214.8k](/packages/zenepay-filament-buddhist-date-picker)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
