NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Swapping models

Point models.calendar, models.schedule or models.exception_rule at a subclass of the packaged model — they are deliberately non-final. Set the keys in config rather than at runtime; a class that is not the packaged model or a subclass of it throws the toolkit’s InvalidConfigurationException naming the key — it is never silently replaced:

// app/Models/Calendar.php
namespace App\Models;

final class Calendar extends \RoundlyConsulting\OpeningHours\Models\Calendar
{
    protected $connection = 'tenant';
}

// config/opening-hours.php
'models' => [
    'calendar' => App\Models\Calendar::class,
    'schedule' => RoundlyConsulting\OpeningHours\Models\Schedule::class,
    'exception_rule' => RoundlyConsulting\OpeningHours\Models\ExceptionRule::class,
],

Transactions use the calendar model’s own connection, so a swapped model on another connection works.

Owner hooks

  • openingHoursTimezone(): ?string — the timezone for calendars without their own.
  • openingHoursDynamicExceptions(): array — DynamicExceptionProvider instances applied to the owner’s calendars.

Custom providers

Implement DynamicExceptionProvider for computed holidays (see Exceptions and holidays) and BusyPeriodProvider for any source of occupied time (see Busy-period providers). Neither needs registration — pass them to the owner hook, withDynamicExceptions() or withBusyPeriods().

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 crypto

By 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.