v1.16.0
What's New
Three additions this release, all backward-compatible.
Eloquent attribute casting — IsEloquentCastable and AsDataCollection
Assign a data object directly as an Eloquent attribute cast:
class Order extends Model
{
protected function casts(): array
{
return ['address' => AddressData::class];
}
}Hydration/serialization go through the same from()/toArray() round trip as everywhere else. Both casters also hook into Eloquent's dirty-check via compare() (Laravel 12+) so a freshly re-serialized value with reordered JSON keys is correctly reported as clean.
No dependency on illuminate/database — same decoupling as HasLaravelIntegration/WireableData.
See Eloquent Attribute Casting.
#[WhenLoaded] — selective relation hydration
fromModel() now hydrates from the model's own attributes only; a relation is included solely when its property is marked #[WhenLoaded('relationName')] and that relation is actually loaded — no more accidentally serializing every eager-loaded relation whether the DTO wants it or not.
See #[WhenLoaded].
#[RejectUnknownKeys] — strict mode
#[RejectUnknownKeys]
class CreateOrderData extends BaseData
{
// ...
}
CreateOrderData::from(['titel' => 'Widget']);
// throws — 'titel' isn't a recognized keyCatches typos and stale API fields instead of silently dropping them — the PHP equivalent of serde's deny_unknown_fields or zod's .strict().
Compiles directly into the generated hydrator, so classes that don't use it pay zero cost.
See #[RejectUnknownKeys].
Full Changelog: v1.15.0...v1.16.0