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

Laravel Useful Casts Laravel Package

renoki-co/laravel-useful-casts

renoki-co/laravel-useful-casts provides a collection of handy custom Eloquent casts for Laravel models, reducing boilerplate when converting database attributes into common PHP types and objects. Drop-in casts keep model code cleaner and more expressive.

View on GitHub
Deep Wiki
Context7

Getting Started

renoki-co/laravel-useful-casts is a grab-bag of ready-made Eloquent cast classes — small implementations of Illuminate\Contracts\Database\Eloquent\CastsAttributes that cover value shapes Laravel doesn't ship (and that you'd otherwise re-write as an accessor + mutator pair in every project). The 2.2.0 release is a support-matrix bump, not an API change: it adds Laravel 10.x and PHP 8.2, and drops Laravel 8.x and PHP 8.0.

Install and pin the version deliberately. 2.2.0 requires PHP 8.1+ and Laravel 9.x or 10.x. If any app or CI job is still on PHP 8.0 or Laravel 8, composer require will resolve you back to the 2.1.x line — check composer.lock rather than assuming you got 2.2.

composer require renoki-co/laravel-useful-casts

Where to look first: the README's cast list, then the corresponding class under src/. Each cast is a single self-contained class with a get() and a set() — reading one is the fastest way to understand what it will and won't do to your column. There is no service provider, no config file to publish, and no migration to run; Eloquent instantiates the cast classes directly.

First use case: pick one column where you currently have both an accessor and a mutator doing symmetric work (a date format, a serialized blob, a normalised value). Swap both for a single cast declaration, then confirm the round-trip — write a value, save, refresh(), and toArray() it. That last step catches most of the real problems (see Gotchas).

Implementation Patterns

Declare casts on the model. The package's job is done at declaration time; usage is just Eloquent:

protected $casts = [
    'published_at' => SomeCast::class,
    'settings'     => SomeCast::class.':optionA,optionB', // ctor args after the colon
];

Colon-separated arguments are passed to the cast's constructor in order, comma-delimited. That is the extension point for per-column configuration — prefer it over subclassing a cast, because a subclass is invisible in the model and easy to forget when reading the schema.

Treat casts as the single source of truth for a column's type. The most common failure mode in codebases that half-adopt this package is a cast plus an accessor on the same attribute — the accessor wins on read, the cast's set() wins on write, and the two drift. When you adopt a cast, delete the accessor and mutator it replaces in the same commit.

Compose with API resources and form requests, not instead of them. A cast normalises storage; a resource controls output shape. Keeping both means toArray()/toJson() stays predictable and you don't have to make your value objects JsonSerializable just to satisfy a serialisation bug (see Gotchas).

Verify with the raw side of the model in tests. assertDatabaseHas and DB::table() see the pre-cast, storage representation; $model->attribute sees the cast value. Write assertions against both so a silently broken set() (which stores the wrong thing but reads back fine in the same request) can't pass CI.

Migrate one column at a time. Because a cast changes both directions at once, a bad cast is a write-path bug on existing rows. Land them individually, with a refresh()-based test, rather than sprinkling ten casts across a model in one PR.

Version the constraint, not the lockfile. In a monorepo or on shared CI, express the floor explicitly ("renoki-co/laravel-useful-casts": "^2.2") so the Laravel 10 requirement is visible at review time rather than discovered in a failed deploy.

Gotchas and Tips

  • 2.2.0 is a support-matrix break. Laravel 8.x and PHP 8.0 are gone. Any app or matrix job still on either must stay on 2.1.x; this is the only thing in the release that can hard-fail a build, and it fails at composer update, not at runtime — which is the good outcome. Verify your php platform config and CI images before bumping.
  • Laravel 11+ isn't in the declared matrix yet. Casts are a stable contract and will very likely work, but the package hasn't declared or tested against 11.x. On L11 you may also be using the casts() method rather than the $casts property — don't assume that path is covered by the package's own tests until a release says so.
  • Null handling is the #1 silent bug. A cast that constructs a value object from null will make a nullable column non-nullable from the model's perspective, and set() returning a non-null value for a null input will quietly write it back. Read each cast's set() before pointing it at a nullable column.
  • set() must return an array. Return [$key => $value] to write, or [] to signal "no change". Returning a bare scalar is a confusing failure, not an error.
  • Unserialisable cast values break toArray(). If a cast returns a plain object, $model->toArray() can throw or emit garbage. Either pick casts whose return types serialise cleanly, or implement Arrayable/JsonSerializable on your value object.
  • Casts do not apply to the query builder. Model::where(...), DB::table()->update(), insert(), upsert(), and chunked bulk operations all bypass set(). You must write the storage representation yourself in those calls — a very common source of "the cast works but the data is wrong".
  • Dirty tracking compares cast values. A value object without sane equality will make isDirty() report true on every save, causing spurious updated_at churn and noisy update listeners. Confirm your casts round-trip stably.
  • getOriginal() is casted; getRawOriginal() is not. Reach for the raw variant when debugging storage.
  • Casts run on every attribute access. Anything involving decryption or parsing pays that cost each time it's touched; avoid invoking such attributes inside a loop over a large collection without caching the result locally.
  • Debugging tip: if a value looks wrong, dump $model->getRawOriginal('column') before suspecting the cast. Nine times out of ten the cast is correct and the write path bypassed it.
  • Extension points are minimal by design. There's no config, no manager class, and no registration hook — you extend by writing your own CastsAttributes implementation (using the package's classes as a reference) or by passing constructor arguments. If you find yourself wanting to subclass, a project-local cast class is usually the cleaner answer.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib