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

Chhankitek Laravel Package

asorasoft/chhankitek

A Laravel/PHP package for working with the Khmer Chhankitek calendar. It helps convert and handle Cambodian lunar dates, supporting calendar calculations and related helpers for Khmer-language applications and Laravel projects.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and confirm discovery.

    composer require asorasoft/chhankitek
    

    Laravel should auto-register the service provider via package discovery. If it doesn't, open vendor/asorasoft/chhankitek/composer.json, read the extra.laravel block, and add the provider (and facade alias, if present) to config/app.php manually.

  2. Find the entry point before writing any code. The README is short, so read src/ directly. Look for the facade class, the underlying converter class, and the return type of the main conversion method. Note whether it returns an object, an array, or a value object — this determines everything about how you consume it.

  3. Publish config if offered. Run php artisan vendor:publish --provider="Asorasoft\Chhankitek\...ServiceProvider" and check for a timezone or locale key. Default to Asia/Phnom_Penh.

  4. First use case — display the lunar date under a Gregorian date. The canonical day-one win is an event card or invoice header that shows both:

    $lunar = Chhankitek::convert(Carbon::parse($event->starts_at));
    // Inspect with dd() first: field names are the real contract.
    

    Typical fields you'll find: lunar day (កើត/រោច), lunar month, Chhankitek year, zodiac animal/year name. Dump one known date (e.g. Khmer New Year, mid-April) and confirm the values against a printed Khmer calendar before building UI around them.

  5. Wrap it immediately. Even on day one, put the package behind your own LunarDateService or a Blade component. With 0 dependents and a single-digit star count, you want one file to change if you swap implementations.

Implementation Patterns

Store AD, compute lunar on read. Persist starts_at as a normal timestamp and derive the lunar representation at render time. Only denormalize lunar fields into columns if you need to query by lunar month — and if you do, store them as integers plus a rendered string, not as a formatted blob.

Blade component for display. A <x-lunar-date :date="$event->starts_at" /> component keeps Khmer formatting, digit conversion, and font classes in one place instead of scattered across views. Give it a format prop (short → "១៥ រោច ខែផល្គុន", long → full Chhankitek string).

API resources. Map the converter output into a stable shape with both scripts:

return [
    'gregorian' => $event->starts_at->toDateString(),
    'lunar' => [
        'khmer' => $khmerString,
        'latin' => $romanizedString, // for non-Khmer readers / search
        'day' => $out->day, 'month' => $out->month, 'year' => $out->year,
    ],
];

Never leak the package's raw return object into JSON — its shape is not a public API and will change across versions.

Calendar-grid / bulk generation. Rendering a month view means 30+ conversions. Compute them in a loop and memoize per date key ($date->toDateString()), or better, build a Collection of the whole month in one service call. Cache the result per month with Cache::remember("lunar.{$year}-{$month}", now()->addDay(), ...) since lunar data for a past month never changes.

Testing with a fixture table. Write a data provider with 10–15 dates you have verified against an authoritative almanac, including Khmer New Year, Pchum Ben, Visak Bochea, and one leap-month year. This is your regression net — it catches package upgrades that silently shift a day.

Digit and script helpers. Khmer numerals (០១២៣៤៥៦៧៨៩) are a common requirement and usually not included. Keep a KhmerNumerals::convert(string $ascii) helper and apply at the presentation layer only, never before storing.

Gotchas and Tips

  • Timezone will bite you first. Lunar day boundaries do not align with UTC midnight. If your app timezone is UTC, a date stored as 2026-04-14 23:00 UTC is already the 15th in Phnom Penh. Set app.timezone to Asia/Phnom_Penh or explicitly pass a timezone-localized Carbon instance; do not pass raw now() from a UTC process.
  • The year is not CE + 543. The Khmer Buddhist Era year increments at Khmer New Year (mid-April), not January 1st. Don't compute it yourself as a sanity check and conclude the package is broken — verify against a reference table first.
  • Leap months are real. The Khmer lunar calendar inserts an extra month (អធិកមាស) on a cycle. Any hand-rolled arithmetic you add around the package's output will be wrong in those years. Treat the month value as opaque.
  • Check the supported range. Conversion packages often only implement a window of years. Validate input dates and fail loudly (throw / abort(422)) rather than rendering a wrong date. Add a min/max config and a Rule for it.
  • Return type instability. If the version you're on returns an array, and the next returns a DTO, your views break. That's the argument for the wrapper class: assert the shape once, map to your own value object, and keep views dependent on your object only.
  • Khmer Unicode handling. Files must be saved UTF-8 without BOM, and your DB columns need utf8mb4_unicode_ci. Beware strlen()/substr() on Khmer strings — use mb_* or Str:: helpers. Khmer rendering also needs a font that supports the script (Noto Sans Khmer, Hanuman) or you'll ship tofu boxes.
  • Pin the version. composer require asorasoft/chhankitek:^x.y with a real constraint, and commit the lockfile. No dependents means no downstream community pressure to catch regressions.
  • Debugging strategy: dump the conversion for the 1st and 15th of the lunar month across a few months. If the waxing/waning flip lands a day early or late, you're almost certainly looking at a timezone issue, not a calendar bug.
  • Extension points are likely thin. Expect a config file at best. If you need locale-aware output or a custom formatter, do it in your wrapper rather than editing vendor/. If you genuinely need to swap the engine later, bind your own interface in a service provider so a future replacement is a one-line container change.
  • Maintenance risk. Last release is recent but the package is young with no dependents. Budget for the possibility of forking it; keeping your integration behind one class makes that a contained afternoon.
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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log