Open source
Appointments for Laravel
composer require roundly-consulting/appointments-for-laravelOverview
A scheduling toolkit for Laravel. Create appointments with durations and time zones, attach any Eloquent model as a participant, block double-bookings, move bookings through a guarded status lifecycle, generate recurring series and export standards-compliant .ics calendar files. One Appointments facade covers it all, with the same API injectable as AppointmentManager. It builds on Roundly’s own provider packages for venue geolocation, guest contacts, booking approvals and post-visit reviews — MIT-licensed, with no third-party dependencies beyond Laravel.
What you get
Facade, DI or actions
Book with Appointments::schedule()->startingAt()->lasting()->create(), inject AppointmentManager, or run the actions with typed DTOs.
Any model as a participant
Users, customers, rooms or vehicles join through one polymorphic table — with a role and per-participant meta.
Guarded status lifecycle
Pending → confirmed → completed, plus cancelled, declined and no-show. Illegal moves throw; every change fires an event.
Double-booking protection
Opt in per call or globally: overlapping bookings for any participant throw — even when two arrive at once, thanks to row locks.
Recurring series
Daily, weekly or monthly rules with interval, count, until and weekday filters — created all-or-nothing in one transaction.
Calendar export & a recording fake
RFC 5545 .ics for one booking or a whole feed; Appointments::fake() records every write for assertScheduled() and friends.
Approvals, reviews & venues
Booking sign-off drives the status, post-visit reviews are verified by attendance, venues support radius search.
Documentation
Installation
Install via Composer, publish the publish-only migrations for appointments and its provider packages, then optionally the config.
Configuration
Every config key and its default — models, key type, table names, time zone, duration, conflicts, recurrence, reviews and approvals.
Schema & custom models
The appointments and participants tables, UUID/ULID participant keys, and how to swap in your own Appointment and Participant models.
The Appointments facade
Tour the Appointments facade — the schedule() builder, DTO creates, the for() handle with participants(), availability, ICS feeds and previews.
DI and actions
Inject AppointmentManager instead of the facade, or run the six actions directly — plus the complete facade method → action map.
Typed DTOs
AppointmentData, ParticipantData and RecurrenceData — the typed DTOs behind create(), createRecurring(), the fluent builder and the actions.
Creating appointments
Create appointments with the fluent Appointments::schedule() builder or a typed DTO — every chainable method, the defaults and the terminal calls.
Durations & time zones
How start, end and duration derive from each other, why instants are stored in UTC, and how to read local times.
Participants
Attach any Eloquent model as a participant with a role and meta, list a model’s appointments with HasAppointments, and add or remove people later.
Status lifecycle
The guarded status state machine — transitions, helper methods, labels, colours and the InvalidStatusTransitionException.
Conflict detection
Block double-bookings per call or globally, inspect the clashing appointments, and check availability with Appointments::isAvailable().
Rescheduling
Move an appointment to a new start, keep or change its duration, guard against conflicts and react to AppointmentRescheduled.
Recurring appointments
Daily, weekly or monthly series with interval, count, until and weekday rules — created all-or-nothing and linked by a group UUID.
Querying
Query scopes for upcoming, past, overlapping and per-participant appointments, plus status filters and ordering.
Calendar export (ICS)
Export one appointment or a whole schedule as RFC 5545 .ics text — status mapping, escaping, GEO, ORGANIZER and ATTENDEE lines.
Venue location
Give appointments a venue name and coordinates, measure distance and find appointments within a radius.
Guest contacts
Store booking emails and phone numbers on an appointment and turn them into calendar ORGANIZER and ATTENDEE mailto lines.
Booking approvals
Require sign-off before a booking is confirmed — flat, quorum, staged or preset workflows that drive the appointment status.
Post-visit reviews
Collect post-visit reviews stamped verified for real attendees, plug in your own attendance resolver and read rating summaries.
Events & exceptions
The seven appointment and participant events, their payloads and when they fire, plus every exception the package throws.
Testing
Record every booking write with Appointments::fake() and its assert methods, then use the model factory and example Pest tests for the rest.
Requirements
PHP 8.4+, Laravel 12 or 13, and six Roundly provider packages installed automatically by Composer.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.