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

Zodiac Laravel Package

intervention/zodiac

Intervention Zodiac is a lightweight PHP package for determining zodiac signs from dates. It supports tropical and sidereal (Vedic) systems, provides sign lookup by date and date ranges for each sign, and works seamlessly in Laravel or any PHP project. No configuration required.

View on GitHub
Deep Wiki
Context7

Getting Started

intervention/zodiac is a small, framework-agnostic value-object package: give it a date, get back a Western tropical zodiac Sign with a name, HTML symbol, localized label, date range, and length. There is no service provider, config file, migration, or facade to publish — day-to-day use is a static factory call.

Minimal steps:

  1. composer require intervention/zodiac:^7.1
  2. Confirm your PHP version is in the supported matrix (7.1.0 adds PHP 8.6 to CI; 8.2/8.3/8.4 users are unaffected).
  3. Read Intervention\Zodiac\Zodiac and Intervention\Zodiac\Sign first — those two classes are the whole public surface.
  4. Try it in php artisan tinker before wiring it into a model.

First use case — deriving a sign from a user's birthdate:

use Intervention\Zodiac\Zodiac;

$sign = Zodiac::fromDate('1980-10-15');

$sign->name();       // "libra"
$sign->html();       // "♎"
$sign->localized();  // localized label
$sign->start();      // DateTime
$sign->end();        // DateTime
$sign->length();     // days in sign

Use name() as your stable key (it is a lowercase slug), and treat html() as a rendering detail.

Implementation Patterns

Model accessor, computed not persisted. Store the birthdate, derive the sign on read. Sign definitions are package data and can shift with a release; persisting "libra" in a column means backfilling later.

protected function zodiac(): Attribute
{
    return Attribute::get(fn () => $this->birthdate
        ? Zodiac::fromDate($this->birthdate)
        : null);
}

API responses — 7.1.0 makes this safer. Sign now implements JsonSerializable, so json_encode($sign) / returning it from a controller produces a payload instead of an empty object. Dump the shape once in a test and pin it:

public function show(User $user)
{
    return response()->json([
        'birthdate' => $user->birthdate,
        'zodiac'    => $user->zodiac, // serializes via JsonSerializable
    ]);
}

If you want a contract you control, keep building the array yourself from name(), html(), localized(), start(), end(). That insulates your API from future serialization changes.

Blade rendering. html() returns an HTML entity, so escape-decoding matters:

<span class="zodiac">{!! $user->zodiac->html() !!}</span>
<span>{{ $user->zodiac->name() }}</span>

Translate from the slug, not the package. If your app is multilingual, use name() as the key in your own lang/{locale}/zodiac.php rather than depending on the package's localized strings. This keeps translation workflow in Laravel and avoids surprises when the app locale and package locale are resolved differently.

Wrap it for the container. Because the API is static, tests that need deterministic signs are easiest if you hide it behind a tiny service or interface binding (ZodiacResolver), then swap a fake in tests.

Batch/computed lists. The object is cheap; a collection map over birthdates is fine. For an index of thousands of users, compute in PHP after the query rather than issuing per-row lookups — there is no database involvement at all.

Validation layer. Pair the call with a date / before_or_equal:today rule, and decide explicitly how you handle null birthdates in the accessor so views never call methods on null.

Gotchas and Tips

  • Serialization change in 7.1.0. Before this release, json_encode($sign) effectively yielded nothing useful (private state, no JsonSerializable). Any test asserting an empty object, or any client relying on a hand-built array, should be updated deliberately. JsonSerializable output is now part of the package's observable behaviour — do not assume it will never change.
  • Cusp dates. Boundaries are fixed calendar ranges, not astronomical calculations. Someone born on the transition day gets whichever side the package assigns. If your product cares (horoscopes, marketing segmentation), write explicit tests for the start/end dates of each sign and be prepared to defend the choice in support tickets.
  • Timezone drift. Zodiac::fromDate() takes a date. If you pass a UTC-shifted Carbon instance for a user born at 23:30 local time, you can land on the wrong day and therefore the wrong sign. Normalize to a date-only value in the user's timezone before calling ($birthdate->toDateString()).
  • HTML entities double-escape. {{ $sign->html() }} renders the literal string &#9806;. Use {!! !!} or html_entity_decode(). Do not run user input through html(), but also do not assume the output is safe to concatenate blindly.
  • No Laravel config to tweak. If you are looking for config/zodiac.php or a facade, stop — there isn't one. Configuration is "which date do I pass in." Container customization is your own wrapper.
  • Locale resolution. Verify localized output in a tinker session with the same locale you set in middleware. If it is wrong or missing for a locale you need, fall back to translating name() yourself.
  • PHP 8.6 support is CI-facing. It signals the constraint is forward-compatible; it does not change runtime behaviour on 8.2–8.5. Upgrading to 7.1.0 is a safe minor bump unless you had snapshot tests around JSON output.
  • Coding-standard externalization is dev-only. The 7.1.0 change moving the coding standard out of the package affects contributors and forks running the package's style tooling, not applications consuming it. If you maintain a fork, re-sync your php-cs-fixer/phpcs setup.
  • Debugging tip. When a sign looks wrong, log the exact string passed to fromDate() and the resulting start()/end() range — nine times out of ten the input date, not the package, is the bug.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource