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.15.5(1mo ago)1.5k141.6k↑10.4%110[1 PRs](https://github.com/ludoguenet/laravel-zap/pulls)1MITPHPPHP &gt;=8.2 &lt;8.6CI failing

Since Jun 8Pushed 1mo ago18 watchersCompare

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

READMEChangelog (10)Dependencies (20)Versions (28)Used By (1)

[![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)`Time range bookable (custom slot + buffer)?`$model->isBookableAtTime('2025-01-15', '09:45', '10:15', null, 30, 15)`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

65

—

FairBetter than 99% of packages

Maintenance90

Actively maintained with recent releases

Popularity60

Solid adoption and visibility

Community32

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 56.1% 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 ~14 days

Recently: every ~20 days

Total

27

Last Release

51d 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 (92 commits)")[![SonnySha](https://avatars.githubusercontent.com/u/39993743?v=4)](https://github.com/SonnySha "SonnySha (15 commits)")[![Sagmedjo](https://avatars.githubusercontent.com/u/46325585?v=4)](https://github.com/Sagmedjo "Sagmedjo (12 commits)")[![nick-potts](https://avatars.githubusercontent.com/u/1109914?v=4)](https://github.com/nick-potts "nick-potts (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)")[![rajabilal555](https://avatars.githubusercontent.com/u/15360941?v=4)](https://github.com/rajabilal555 "rajabilal555 (3 commits)")[![olivermbs](https://avatars.githubusercontent.com/u/37539998?v=4)](https://github.com/olivermbs "olivermbs (3 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (3 commits)")[![gmlo89](https://avatars.githubusercontent.com/u/874420?v=4)](https://github.com/gmlo89 "gmlo89 (3 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)")[![ziming](https://avatars.githubusercontent.com/u/679513?v=4)](https://github.com/ziming "ziming (1 commits)")[![deshack](https://avatars.githubusercontent.com/u/2034213?v=4)](https://github.com/deshack "deshack (1 commits)")[![daliendev](https://avatars.githubusercontent.com/u/53065505?v=4)](https://github.com/daliendev "daliendev (1 commits)")[![raphaelstolt](https://avatars.githubusercontent.com/u/48225?v=4)](https://github.com/raphaelstolt "raphaelstolt (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.

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

Office365 Adapter for CalendArt

1313.8k](/packages/calendart-office365-adapter)

PHPackages © 2026

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