Download the PHP package puntodev/bookables without Composer
On this page you can find all versions of the php package puntodev/bookables. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download puntodev/bookables
More information about puntodev/bookables
Files in puntodev/bookables
Package bookables
Short Description Bookable Library
License MIT
Homepage https://github.com/puntodev/bookables
Informations about the package bookables
Bookables
A small, framework-agnostic PHP library for computing bookable availability and time slots. You describe when something is available — with a recurring weekly schedule or a single date range — and Bookables turns that into concrete time ranges and ready-to-book slots for any window of dates.
It's a pure domain library: no framework coupling, no database, no HTTP. Drop it into
any PHP application (Laravel, Symfony, plain PHP, …) that needs to answer "when can
this resource be booked?". It builds on nesbot/carbon
for date/time math and league/period for the
Period value object used to represent ranges and slots.
Requirements
- PHP
>=8.4 <9.0 ext-json
Installation
Install via Composer:
Concepts
The library is organized around a simple pipeline:
| Piece | Responsibility |
|---|---|
WeeklySchedule |
A value object describing recurring weekly availability (per-day time ranges). JSON/array serializable, with validation. |
Agenda (contract) |
possibleRanges(from, to) → the concrete Period ranges available within a date window. |
WeeklyScheduleAgenda |
An Agenda backed by a WeeklySchedule. |
SingleDateRangeAgenda |
An Agenda for one fixed start/end range. |
TimeSlotter (contract) |
makeSlotsForDates(start, end) → the bookable slots (as Periods) within a window. |
AgendaSlotter |
Slices an Agenda's ranges into fixed-duration slots, with optional gaps before/after. |
DaySlotter |
Produces sliding-window slots across the whole day (ignores any agenda). |
HasAgenda / TimeBookable (contracts) |
Interfaces you implement on your own entities (e.g. a professional, room, or resource). |
All ranges and slots are returned as
League\Period\Periodobjects. Call->toIso8601()(or anyPeriodmethod) to inspect them.
Usage
1. Define a weekly schedule
A WeeklySchedule describes, for each day of the week, the time ranges during which
the resource is available. Build one from an array or from JSON — both validate the
input and throw an Exception if it's malformed.
The JSON form (handy for persisting a schedule in a database column):
There's also a ready-made sample schedule (Mon–Fri 08:00–12:00 & 14:00–18:00, Sat 10:00–12:00):
Schedule JSON schema
| Key | Type | Description |
|---|---|---|
daily |
object | Map of day-of-week (Sun, Mon, Tue, Wed, Thu, Fri, Sat) to a list of { "start": "HH:MM", "end": "HH:MM" } ranges. Times must be a zero-padded time of day (HH:MM or HH:MM:SS, 00:00–23:59); relative expressions like now are rejected. start must be before end. |
hours_in_advance |
int | Minimum booking notice, in hours. Metadata only — stored and exposed via hoursInAdvance(), but not enforced by the slotters (see notes below). |
disable_all |
bool | When true, the schedule yields no availability regardless of daily. Optional, defaults to false. |
2. Get available ranges from an agenda
An Agenda turns availability into the concrete date ranges that fall inside a
requested [from, to] window.
For one-off availability that isn't weekly (e.g. a single open window), use
SingleDateRangeAgenda. It returns the intersection of its fixed range with the
requested window (or no range at all if they don't overlap):
3. Turn ranges into bookable slots
A TimeSlotter slices ranges into the actual slots a user can book.
AgendaSlotter produces fixed-duration slots inside each of an agenda's ranges:
You can reserve a gap before and/or after each appointment (in minutes). The stride
between slot starts becomes duration + max(timeAfter, timeBefore):
DaySlotter ignores agendas entirely and lays a sliding window of slots across
the full 24 hours of each day — useful when availability is "any time" and you only
care about duration and stepping. When step is smaller than duration, slots
overlap.
Timezones
Agendas compute availability in the timezone of the Carbon instances you pass in.
WeeklyScheduleAgenda interprets the schedule's HH:MM times in that timezone. Note
that Period::toIso8601() renders in UTC (Z), so the same wall-clock schedule in
different timezones produces different UTC output:
Modeling your own bookable entities
The HasAgenda and TimeBookable contracts are there for your application to
implement on its own models — for example, a professional or room that exposes an
agenda:
Notes & caveats
hours_in_advanceis not enforced by the slotters. It's carried as metadata (available viahoursInAdvance()); filtering out slots that are too soon is the consuming application's responsibility.disable_allis enforced — aWeeklyScheduleAgendaover a disabled schedule yields no ranges.- Ranges and slots are immutable
League\Period\Periodobjects; all internal date math uses Carbon's immutable variants. -
Requested date ranges are capped.
WeeklyScheduleAgenda,AgendaSlotterandDaySlottergenerate one entry per day (and per slot) in the[from, to]window, so an unbounded range would exhaust memory. Each takes an optionalmaxDaysargument (default366) and throwsPuntodev\Bookables\Exceptions\DateRangeTooLargeExceptionwhen the window is larger. Pass0(or less) to disable the limit if you have your own bound: - Slot durations must be positive.
AgendaSlotter(duration) andDaySlotter(duration,step) reject non-positive values withInvalidArgumentException;timeAfter/timeBeforemust not be negative.
Testing
Generate an HTML coverage report:
Changelog
Please see CHANGELOG for what has changed recently.
Releasing
Releases are cut from GitHub and the changelog is kept in sync automatically:
- Merge the pull requests you want to ship into
master. Label them so the notes group nicely (security,enhancement,bug,dependencies,documentation); grouping is configured in.github/release.yml. - On GitHub, go to Releases → Draft a new release, create a
vX.Y.Ztag following SemVer, and click Generate release notes. - Publish the release. Packagist picks up the new tag, and the
update-changelog.ymlworkflow writes the release notes intoCHANGELOG.mdand commits them back tomaster.
The Unreleased section in the changelog is just an anchor — release notes flow
from the published GitHub release, so there is no changelog to edit by hand.
Contributing
Please see CONTRIBUTING for details. In short: keep the library framework-agnostic, write everything in English, and include tests with every change.
Security
If you discover any security-related issues, please email [email protected] instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see the License File for more information.
All versions of bookables with dependencies
ext-json Version *
league/period Version ^5.3
nesbot/carbon Version ^3.11