NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Opening Hours for Laravel

Dostupnosť a sloty

Dostupnosť nevie nič o rezerváciách — pýta sa zdroja obsadenosti, čo je obsadené. availability() vráti nemenný builder; každý setter vráti kópiu:

use Carbon\CarbonImmutable;
use RoundlyConsulting\OpeningHours\Availability\BusyPeriod;
use RoundlyConsulting\OpeningHours\Facades\OpeningHours;

$availability = OpeningHours::for($clinic)->availability()
    ->withBusyPeriods(fn (CarbonImmutable $start, CarbonImmutable $end) => $bookings->between($start, $end))
    ->capacity(2)                           // parallel bookings (a range's own capacity wins)
    ->buffers(before: 5, after: 10)         // must fall inside opening hours by default
    ->minNotice(minutes: 120)
    ->horizon(days: 60);

$result = $availability->check($start, $end);   // AvailabilityResult
$result->available;                             // bool
$result->reason;                                // ?UnavailableReason: invalid_range, in_past, too_soon, too_far, closed, busy
$result->conflict;                              // ?BusyPeriod
$result->message();                             // translated reason
$availability->isAvailable($start, $end, weight: 1);

Nastavenia

MetódaVýznam
withBusyPeriods($busy)Zdroj obsadenosti: BusyPeriodProvider, iterable s BusyPeriod alebo closure (start, end), ktorá ich vráti.
capacity(int)Predvolená paralelná kapacita (≥ 1); vlastná kapacita rozsahu má prednosť; inak 1.
buffers(before:, after:, withinOpeningHours: true)Minúty blokované okolo každej rezervácie; predvolene musia spadať do otváracích hodín. Pri withinOpeningHours: false sa zatvorená časť rezervy počíta s kapacitou rozsahu, v ktorom rezervácia začína (before) alebo končí (after).
minNotice(minutes:)Najskorší začiatok = teraz + n skutočných minút.
horizon(days:)Najneskorší začiatok = teraz + n kalendárnych dní podľa miestneho času (vrátane); null = bez limitu.
at($instant)Vyhodnotiť k tomuto okamihu namiesto teraz.

Prečo termín nie je dostupný

check() vyhodnocuje v pevnom poradí a vráti prvý dôvod zlyhania; message() ho vráti preložený:

DôvodKedy
invalid_rangeKoniec nie je po začiatku.
in_pastZačiatok je v minulosti.
too_soonZačiatok spadá do minimálneho predstihu.
too_farZačiatok je za horizontom.
closedOtváracie hodiny nepokrývajú rezerváciu aj s časovými rezervami.
busyKapacita je niekde v obsadenom okne prekročená; conflict obsahuje prvé prekrývajúce sa obsadené obdobie.

Sloty

$slots = $availability->slots('2026-10-01', '2026-10-07')     // whole local days, inclusive
    ->duration(30)->step(15)->alignTo(15)
    ->limit(200)
    ->get();                                                   // SlotCollection
$slots->groupByDate();                                         // ['2026-10-01' => [Slot, …], …]

foreach ($slots as $slot) {
    $slot->start;                                              // CarbonImmutable
    $slot->end;
    $slot->remainingCapacity;
}

$all = $availability->slots('2026-10-01', '2026-10-01')
    ->duration(60)
    ->includeUnavailable()                                     // also slots that failed on capacity
    ->get();
$all->available();                                             // only the bookable ones

$availability->slots('2026-10-01', '2026-10-01')->duration(60)->first();   // ?Slot
$availability->nextAvailableSlot(duration: 30);                // ?Slot
$availability->freePeriods('2026-10-01', '2026-10-01');        // list<Period>
  • slots($from, $to) prijíma dátumy (celé miestne dni vrátane) alebo okamihy (koniec vylúčený). duration() je povinné; step() je predvolene rovné dĺžke; alignTo() je predvolene rovné kroku a počíta sa od miestnej polnoci.
  • weight() rezervuje naraz viac jednotiek kapacity; includeUnavailable() vráti aj sloty, ktoré zlyhali na kapacite (dôvod busy); limit() obmedzí výsledok na limits.slots.
  • get() vráti SlotCollection s metódami available(), groupByDate() a toArray(); first() vráti prvý ?Slot.
  • Každý Slot má start, end, available, remainingCapacity a reason.
  • nextAvailableSlot() prezerá search_days miestnych dní dopredu a hľadá po častiach, takže sa sám zmestí do max_query_days.
  • Mriežka sa zarovnáva podľa miestneho času a ostáva správna aj pri preskočenej hodine a 30-minútových posunoch; viacdňové sloty (prenájmy) fungujú rovnako.

Model kapacity

Kapacita otvorenia je range.capacity ?? kapacita dostupnosti ?? 1, pričom prekrývajúce sa rozsahy berú maximum. Rezervácia sa zmestí, ak usage + weight ≤ capacity v každom okamihu [start − before, end + after). Pri buffers(withinOpeningHours: false) sa zatvorená časť rezervy počíta s kapacitou rozsahu, v ktorom rezervácia začína (before) alebo končí (after). Dĺžka, predstih aj časové rezervy sú skutočný uplynulý čas; horizont sa počíta v kalendárnych dňoch podľa miestneho času.

Pri rezervácii overte znova

Dostupnosť je iba čítanie. Keď rezerváciu ukladáte, overte ju znova vo vlastnom zámku alebo cez unikátne obmedzenie — medzi kontrolou a zápisom môže ten istý slot rezervovať iný request:

use Illuminate\Support\Facades\Cache;

Cache::lock("book:{$vet->id}:{$start}", 10)->block(5, function () use ($availability, $vet, $start, $end): void {
    abort_unless($availability->isAvailable($start, $end), 409);

    Appointment::query()->create(['vet_id' => $vet->id, 'starts_at' => $start, 'ends_at' => $end]);
});

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.