Weave 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

Calendar Laravel Package

korchid/calendar

korchid/calendar is a flexible calendar package for Laravel and PHP applications, offering a simple API to generate date grids, format dates, and render customizable calendar views for dashboards, schedulers, and booking interfaces. Lightweight and easy to integrate into existing projects.

View on GitHub
Deep Wiki
Context7

Getting Started

orchid/calendar is a presentation-layer calendar builder for Laravel: it generates day/week/month/year grid markup (Blade views, Carbon-driven) that you embed in your own controller + view. It does not store events — you bring the data.

composer require orchid/calendar

Package discovery registers the service provider; there is normally nothing to add to config/app.php. If you need to change markup, publish the namespaced views (calendar::) into resources/views/vendor/calendar and edit there rather than forking.

Where to look first:

  1. The entry-point class (the Calendar factory under Orchid\Calendar\) — this is what you type in your controller.
  2. The View/ classes (Day, Week, Month, Year) — these hold the actual build logic and are where you go when the grid looks wrong.
  3. resources/views/ inside the package — the Blade templates that produce the markup; the fastest way to understand what data each granularity receives.

First use case — drop a month grid onto a page:

use Orchid\Calendar\Calendar;

Route::get('/schedule', function () {
    return view('schedule', [
        'calendar' => Calendar::create()->months()->render(),
    ]);
});

Then in Blade, echo it raw (it is HTML, not escaped text):

{!! $calendar !!}

Note on version: v1.0.1 is a patch release against v1.0.0 with no documented API changes (the release notes only link the diff). Bumping within ^1.0 is safe; pin the constraint and re-read the diff before moving to 1.1.

Implementation Patterns

Granularity is a choice, not a config. Pick the view type per screen — day/week for operational dashboards, month/year for overviews. Don't try to make one calendar serve both; build two and route between them.

Overlay your own events by date key. The package renders an empty grid; the work is mapping your Eloquent models onto dates. Query once for the visible range, key by Y-m-d, then pass the map into the view:

$start = Carbon::parse(request('month', 'now'))->startOfMonth()->startOfWeek();
$end   = $start->copy()->endOfMonth()->endOfWeek();

$events = Event::query()
    ->whereBetween('starts_at', [$start, $end])
    ->get()
    ->groupBy(fn ($e) => $e->starts_at->toDateString());

return view('schedule', [
    'calendar' => Calendar::create()->months()->render(),
    'events'   => $events,
]);

Drive navigation from the query string. ?month=2024-05 (or ?date=…) parsed with Carbon::parse() for the anchor, plus prev/next links built from copy()->subMonthNoOverflow(). Keeps the calendar stateless and shareable via URL.

Embed in Orchid Screens like any other block. Inside a screen's layout(), wrap the rendered HTML in a Layout/Wrapper (or a Modal/Rows element) rather than a field — it's read-only output, so Field types are the wrong abstraction.

Cache static or rarely-changing grids. The rendered string is deterministic for a given anchor date + locale + week start. Cache::remember("cal:{$anchor}:{$locale}", now()->addHour(), fn () => ...) removes the cost on high-traffic dashboards; bust on event write.

Freeze time in tests. Carbon::setTestNow() before rendering and assert on the produced markup; this is the only reliable way to keep grid assertions stable across months.

Gotchas and Tips

  • Echo raw. Wrap in {!! !!}. Using {{ }} silently produces escaped tags and a "blank" calendar — a very common first-day bug.
  • Locale drives day/month names, not your app locale automatically. Set the Carbon/application locale (App::setLocale() / Carbon::setLocale()) before rendering, and re-render per locale rather than caching one locale's output under a shared key.
  • Timezone drift. Carbon uses config('app.timezone'). If your stored timestamps are UTC but the UI is local, convert before grouping into date buckets — otherwise events land on the wrong day near midnight.
  • Week start is configurable and bites you. If Monday-first is expected but the grid starts Sunday, check the week-start setting before touching templates. Same for subMonth() vs subMonthNoOverflow() — anchoring on the 31st will skip months.
  • Range queries must be padded. Querying exactly startOfMonth..endOfMonth loses the leading/trailing days the grid still renders. Always expand to startOfWeek/endOfWeek of the anchor.
  • N+1 on multi-week views. A day-level view over a month means many buckets; eager-load relations on the single range query above instead of querying per cell.
  • No persistence, no event model. If you find yourself looking for an events table or a save method, you're in the wrong package — that belongs in your app domain.
  • Extension points, in order of safety: custom Blade view (view override) → wrapper partial around the rendered output → subclassing the View/* class. Avoid editing the vendor directory; the package namespace views support publishing precisely so you don't have to.
  • Debugging a wrong grid: dump what the view class produces (the date buckets) before the template executes. If buckets are right and the markup is wrong, it's the Blade template; if buckets are wrong, it's Carbon (timezone, week start, or locale).
  • Pre-1.1 API surface. Still on the 1.x line with a terse changelog — treat the builder method names as stable-but-unpromised, keep usage confined to your own controller/view layer (thin adapter), and re-check after any minor bump.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings