Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Zap Laravel Package

laraveljutsu/zap

Zap is a Laravel scheduling package to manage availabilities, appointments, blocked times, and custom schedules for any resource (doctors, rooms, employees). Query availability, prevent overlaps, and build booking, shift, or shared space workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laraveljutsu/zap
    php artisan vendor:publish --provider="Zap\ZapServiceProvider"
    php artisan migrate
    
  2. Make a model schedulable:

    use Zap\Models\Concerns\HasSchedules;
    
    class Doctor extends Model
    {
        use HasSchedules;
    }
    
  3. First use case: Define working hours for a doctor:

    use Zap\Facades\Zap;
    
    Zap::for($doctor)
        ->named('Office Hours')
        ->availability()
        ->forYear(2025)
        ->addPeriod('09:00', '12:00')
        ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
        ->save();
    

Where to Look First

  • Documentation: laravel-zap.com
  • Quick Start: Focus on Zap::for($model)->named()->[availability|appointment|blocked]()->...->save()
  • Recurrence Patterns: /schedule-patterns section for common use cases
  • Query Methods: /query--check-availability for availability checks

Implementation Patterns

Core Workflow

  1. Define Schedules:

    Zap::for($resource)
        ->named('Schedule Name')
        ->[availability|appointment|blocked]()
        ->[recurrencePattern]()
        ->[timePeriods]()
        ->save();
    
  2. Query Availability:

    $slots = $resource->getBookableSlots('2025-01-15', 60, 15);
    $nextSlot = $resource->getNextBookableSlot('2025-01-15', 60, 15);
    
  3. Create Appointments:

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

Integration Tips

  • Validation: Use noOverlap(), maxDuration(), or workingHoursOnly() for custom rules:

    ->noOverlap()
    ->maxDuration(120)
    ->workingHoursOnly('09:00', '17:00')
    
  • Recurrence Patterns: Combine patterns for complex schedules:

    ->weeklyOdd(['monday', 'wednesday'])
    ->everyThreeWeeks(['friday'])
    
  • Metadata: Attach custom data to schedules:

    ->withMetadata(['room_type' => 'conference', 'capacity' => 10])
    
  • Conflict Detection:

    if (Zap::hasConflicts($schedule)) {
        // Handle conflict
    }
    

Common Use Cases

Use Case Implementation Pattern
Doctor Appointments appointment() + getBookableSlots()
Room Bookings availability() + blocked()
Employee Shifts weekDays() + biweekly()
Recurring Events firstWednesdayOfMonth() + addPeriod()
Custom Validation noOverlap() + maxDuration()

Gotchas and Tips

Pitfalls

  1. Timezone Handling:

    • Always use UTC or a consistent timezone in your application. Zap normalizes timezones internally, but mismatches can cause edge cases.
    • Example: If your app uses America/New_York but Zap expects UTC, week boundaries (e.g., startOfWeek) may misalign.
  2. UUID/ULID Models:

    • If using non-integer primary keys (UUIDs/ULIDs), publish migrations and config before running migrate:
      php artisan vendor:publish --tag=zap-migrations
      php artisan vendor:publish --tag=zap-config
      
    • Update migrations to use uuid() and uuidMorphs() instead of foreignId().
  3. Deprecated Methods:

    • Avoid isAvailableAt(). Use isBookableAt() or isBookableAtTime() instead.
  4. Overlap Logic:

    • By default, noOverlap() prevents appointments from conflicting with availabilities/blocked times. Explicitly allow overlaps with allowOverlap() if needed.
  5. Date Ranges:

    • forYear(2025) creates schedules for every occurrence in the year. For large ranges, consider from()->to() with explicit recurrence patterns.

Debugging Tips

  • Check Conflicts:

    $conflicts = Zap::findConflicts($schedule);
    dd($conflicts);
    
  • Inspect Schedules:

    $doctor->schedules()->get(); // All schedules
    $doctor->appointmentSchedules()->get(); // Only appointments
    
  • Log Recurrence: Enable debug mode in config/zap.php:

    'debug' => env('ZAP_DEBUG', false),
    
  • Time Period Validation: Ensure addPeriod() uses 24-hour format (e.g., '09:00' not '9:00 AM').

Extension Points

  1. Custom Schedule Types: Extend Zap\Models\Schedule to add domain-specific logic:

    namespace App\Models;
    
    use Zap\Models\Schedule as BaseSchedule;
    
    class CustomSchedule extends BaseSchedule
    {
        protected $customRule = 'my_rule';
    }
    
  2. Validation Rules: Add custom rules to Zap\Rules\ScheduleRule or override in your model:

    use Zap\Rules\ScheduleRule;
    
    class Doctor extends Model
    {
        use HasSchedules;
    
        protected function customValidationRules()
        {
            return [
                'max_patients_per_hour' => 5,
            ];
        }
    }
    
  3. Query Scopes: Add global scopes to filter schedules:

    namespace Zap\Models;
    
    use Illuminate\Database\Eloquent\Builder;
    
    class Schedule extends Model
    {
        public function scopeActive(Builder $query)
        {
            return $query->where('ends_at', '>', now());
        }
    }
    
  4. Event Listeners: Listen for schedule events (e.g., Zap\Events\ScheduleCreated):

    use Zap\Events\ScheduleCreated;
    
    Event::listen(ScheduleCreated::class, function ($schedule) {
        // Send notification, log, etc.
    });
    

Configuration Quirks

  • Buffer Minutes: Adjust time_slots.buffer_minutes in config/zap.php to control padding between slots (default: 15).

  • Conflict Detection: Set conflict_detection to 'strict' or 'lenient' based on your overlap tolerance.

  • Default Rules: Override default_rules to enforce global constraints:

    'default_rules' => [
        'no_overlap' => true,
        'max_duration' => 120, // 2 hours
    ],
    

Performance Tips

  • Indexing: Ensure schedulable_id and schedule_type are indexed in the schedules table for large datasets.

  • Caching: Cache frequent availability queries:

    $slots = Cache::remember("slots_{$doctor->id}_{$date}", now()->addHours(1), function () use ($doctor, $date) {
        return $doctor->getBookableSlots($date, 60, 15);
    });
    
  • Batch Processing: Use Zap::for($model)->batch() for bulk schedule creation:

    Zap::for($doctor)->batch()
        ->named('Bulk Appointments')
        ->appointment()
        ->from('2025-01-01')->to('2025-01-31')
        ->addPeriod('10:00', '11:00')
        ->save();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui