happyr/birthday-bundle
A Symfony bundle from HappyR that adds birthday support to your application. It offers birthday-related services and simple configuration to help you track and manage user birthdays within Symfony projects.
Verdict up front: this is not a Laravel package. happyr/birthday-bundle is a Symfony bundle (type: symfony-bundle) with Twig extensions, DI service definitions, and Doctrine ORM repositories. Laravel has no bundle kernel, no Twig, no Doctrine bundle, and no extra.laravel.providers discovery. The stack-fit score is effectively zero, so any TPM decision framed as "adopt or not" collapses into "port or not."
Architecture fit. The domain is framework-neutral in concept and roughly 200–400 LOC across three concerns: a contract for entities exposing a birthday date, a manager that answers "whose birthday is today / within N days," and a view helper that renders a widget. The packaging is Symfony 2/3-era and does not transfer. What a TPM should extract is the scoping pattern, not the artifact: birthday field on the user model, a date-window query, a presentation partial.
Technical risk — high. Last release 2017-11-14 puts it in the PHP 7.0/7.1 and Symfony 2.8/3.x window, with Doctrine ~2.5. It will not resolve cleanly on PHP 8.2+ or Laravel 10/11 without forking composer.json and --ignore-platform-reqs. Add 0 stars, 0 dependents, and no issue corpus, and you have a supply-chain liability with a bus factor of zero. Nothing in the package answers the questions that actually matter for this feature: timezone of the "today" boundary, Feb 29 policy, consent over birth-year visibility, i18n of date formats, or notification channel.
Leverage for a TPM. Realistically this package supports three product decisions and nothing else:
Key questions for the requestor:
Stack fit. No shared abstractions beyond PSR interfaces. Twig becomes Blade; Doctrine annotations become Eloquent casts; bundle DI YAML becomes a service provider plus config/birthday.php.
Migration path — port, do not depend. Vendor the repository as a read-only reference and build a first-party acme/birthday package behind an interface so it can be swapped if the spike fails.
| Upstream | Laravel equivalent |
|---|---|
BirthdayInterface |
HasBirthday trait, birthday cast to immutable_date |
BirthdayManager |
BirthdayService with scopeBirthdayToday / scopeBirthdayWithin(int $days) |
Twig BirthdayExtension |
Blade component <x-birthday-widget> |
| Bundle DI config | BirthdayServiceProvider + mergeConfigFrom / publishes |
Compatibility. Target PHP ^8.1, Laravel ^10|^11, zero Symfony dependencies, no doctrine/dbal. Use Carbon for date math and timezone conversion. Avoid MONTH(birthday)=? AND DAY(birthday)=? predicates — they defeat indexes; persist a birthday_month_day generated column indexed alongside a tenant key.
Sequencing for the TPM to schedule:
If reuse is mandated. Forking to bump constraints and abstract out Doctrine is more work than the rewrite and leaves us owning a fork of a dead project. Document that trade-off explicitly for the approver rather than absorbing it silently in the sprint.
Maintenance. Upstream is dormant, so every future PHP or Laravel upgrade becomes our problem. A first-party port is a few hundred lines with a named owner and tests — a few hours per quarter. A fork is a permanently owned artifact written in unfamiliar idioms; materially worse.
Support. No vendor, no issue triage, no security advisories, no Stack Overflow corpus. Onboarding is read-the-source. Because birthdays are personal data, our security team owns the surface regardless of provenance — the package choice removes none of that obligation.
Scaling. The widget is cheap; a naive query is not. At six-figure user counts, month/day extraction predicates force a scan per request. Mitigate with the generated indexed column plus a per-user, per-day fragment cache keyed to local midnight. Watch N+1 if the manager returns full entities and the partial touches relations — select only id and display name.
Failure modes to design against:
Ramp-up. Low for the port (small, well-understood domain); moderate for the privacy/compliance review. A mid-level Laravel developer ships it in 1–3 days; add half a day for tests and a day for sign-off.
Recommendation: do not adopt as a dependency. Use it strictly as a design reference and port the concept in-house. Zero stars, zero dependents, and a 2017 release with no PHP 8 support is a decisive signal — the cost of owning a dead Symfony bundle exceeds the cost of writing the ~300 lines ourselves.
How can I help you explore Laravel packages today?