PHPackages                             jessarcher/laravel-castable-data-transfer-object - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jessarcher/laravel-castable-data-transfer-object

AbandonedArchivedLibrary[Utility &amp; Helpers](/categories/utility)

jessarcher/laravel-castable-data-transfer-object
================================================

Automatically cast JSON columns to rich PHP objects in Laravel using Spatie's data-transfer-object class

v2.3.0(3y ago)325695.8k↑23.7%22[1 issues](https://github.com/jessarcher/laravel-castable-data-transfer-object/issues)[1 PRs](https://github.com/jessarcher/laravel-castable-data-transfer-object/pulls)1MITPHPPHP ^8.0

Since Oct 22Pushed 2y ago5 watchersCompare

[ Source](https://github.com/jessarcher/laravel-castable-data-transfer-object)[ Packagist](https://packagist.org/packages/jessarcher/laravel-castable-data-transfer-object)[ Docs](https://github.com/jessarcher/laravel-castable-data-transfer-object)[ RSS](/packages/jessarcher-laravel-castable-data-transfer-object/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (9)Versions (9)Used By (1)

Laravel Castable Data Transfer Object
=====================================

[](#laravel-castable-data-transfer-object)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d0ef7babfe6ee04c54af2ae66ac46b24b1b41de00c378337e9aa51531529fb56/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6573736172636865722f6c61726176656c2d6361737461626c652d646174612d7472616e736665722d6f626a6563742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jessarcher/laravel-castable-data-transfer-object)[![GitHub Tests Action Status](https://camo.githubusercontent.com/a1c24500cfe5ae3f8f79933f8c6f580d31e820b68b0b51437fdee7cc944fa953/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6a6573736172636865722f6c61726176656c2d6361737461626c652d646174612d7472616e736665722d6f626a6563742f72756e2d74657374733f6c6162656c3d7465737473)](https://github.com/jessarcher/laravel-castable-data-transfer-object/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/01a7e40376df8fbf8aa7aedeef64d6cbcfe659cf3eb404cee4369321dada0946/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6a6573736172636865722f6c61726176656c2d6361737461626c652d646174612d7472616e736665722d6f626a6563742f436865636b253230262532306669782532307374796c696e673f6c6162656c3d636f64652532307374796c65)](https://github.com/jessarcher/laravel-castable-data-transfer-object/actions?query=workflow%3A%22Check+%26+fix+styling%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/50b49f36c5bd7c67fe3b81ab9920b148eef04ce634436a0da7f4b9ff624f1036/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a6573736172636865722f6c61726176656c2d6361737461626c652d646174612d7472616e736665722d6f626a6563742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/jessarcher/laravel-castable-data-transfer-object)

Laravel is awesome. Spatie's [data transfer object](https://github.com/spatie/data-transfer-object) package for PHP is awesome. They're already good friends, but now they're taking their relationship to the next level 💕

Have you ever wanted to cast your JSON columns to a value object?

This package gives you an extended version of Spatie's `DataTransferObject` class, called `CastableDataTransferObject`.

Under the hood it implements Laravel's [`Castable` interface](https://laravel.com/docs/8.x/eloquent-mutators#castables) with a Laravel [custom cast](https://laravel.com/docs/8.x/eloquent-mutators#custom-casts) that handles serializing between the `DataTransferObject` (or a compatible array) and your JSON database column.

For an in-depth explanation of what it's actually doing and the motivation behind it, check out [the blog post that spawned it](https://jessarcher.com/blog/casting-json-columns-to-value-objects/).

This package has also been featured on [Laravel News](https://laravel-news.com/laravel-castable-data-transfer-object)!

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require jessarcher/laravel-castable-data-transfer-object
```

Usage
-----

[](#usage)

### 1. Create your `CastableDataTransferObject`

[](#1-create-your-castabledatatransferobject)

Check out the readme for Spatie's [data transfer object](https://github.com/spatie/data-transfer-object) package to find out more about what their `DataTransferObject` class can do.

```
namespace App\Values;

use JessArcher\CastableDataTransferObject\CastableDataTransferObject;

class Address extends CastableDataTransferObject
{
    public string $street;
    public string $suburb;
    public string $state;
}
```

(Note: I like to put these in `App\Values` because I'm using them as a value object and not just a plain DTO. Feel free to put it anywhere you like!)

### 2. Configure your Eloquent attribute to cast to it:

[](#2-configure-your-eloquent-attribute-to-cast-to-it)

Note that this should be a `jsonb` or `json` column in your database schema.

```
namespace App\Models;

use App\Values\Address;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'address' => Address::class,
    ];
}
```

And that's it! You can now pass either an instance of your `Address` class, or even just an array with a compatible structure. It will automatically be cast between your class and JSON for storage and the data will be validated on the way in and out.

```
$user = User::create([
    // ...
    'address' => [
        'street' => '1640 Riverside Drive',
        'suburb' => 'Hill Valley',
        'state' => 'California',
    ],
])

$residents = User::where('address->suburb', 'Hill Valley')->get();
```

But the best part is that you can decorate your class with domain-specific methods to turn it into a powerful value object.

```
$user->address->toMapUrl();

$user->address->getCoordinates();

$user->address->getPostageCost($sender);

$user->address->calculateDistance($otherUser->address);

echo (string) $user->address;
```

### Using defaults for null database values

[](#using-defaults-for-null-database-values)

By default, if a database value is `null`, then the model attribute will also be `null`. However, sometimes you might want to instantiate the attribute with some default values.

To achieve this, you may provide an additional `nullable` [Cast Parameter](https://laravel.com/docs/eloquent-mutators#cast-parameters) to ensure the caster gets instantiated.

```
namespace App\Models;

use App\Values\Address;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'settings' => Settings::class . ':nullable',
    ];
}
```

This will ensure that the `Settings` caster is instantiated even when the `settings` column in the database is `null`.

You may then specify some default values in the cast which will be used instead.

```
use JessArcher\CastableDataTransferObject\CastableDataTransferObject;

class Settings extends CastableDataTransferObject
{
    public string $title = 'Default';
}
```

### Controlling serialization

[](#controlling-serialization)

You may provide the caster with flags to be used for serialization by adding the `CastUsingJsonFlags` attribute to your object:

```
use JessArcher\CastableDataTransferObject\CastableDataTransferObject;
use JessArcher\CastableDataTransferObject\CastUsingJsonFlags;

#[CastUsingJsonFlags(encode: JSON_PRESERVE_ZERO_FRACTION)]
class Address extends CastableDataTransferObject {}
```

### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Jess Archer](https://github.com/jessarcher)
- [Jeremiasz Major](https://github.com/jrmajor)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

Laravel Package Boilerplate
---------------------------

[](#laravel-package-boilerplate)

This package was generated using the [Laravel Package Boilerplate](https://laravelpackageboilerplate.com).

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity55

Moderate usage in the ecosystem

Community22

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 61.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~124 days

Recently: every ~176 days

Total

8

Last Release

1161d ago

Major Versions

v0.0.2 → v1.0.02020-11-27

v1.0.0 → v2.0.02021-04-06

PHP version history (3 changes)v0.0.1PHP ^7.4

v1.0.0PHP ^7.4 || ^8.0

v2.0.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/32aef761bc4f0c353a77ac2d7b4541a5090f69e7a836f0e208ca2979d6a67a97?d=identicon)[jessarcher](/maintainers/jessarcher)

---

Top Contributors

[![jessarcher](https://avatars.githubusercontent.com/u/4977161?v=4)](https://github.com/jessarcher "jessarcher (40 commits)")[![jrmajor](https://avatars.githubusercontent.com/u/26096713?v=4)](https://github.com/jrmajor "jrmajor (18 commits)")[![DanielGSoftware](https://avatars.githubusercontent.com/u/49187378?v=4)](https://github.com/DanielGSoftware "DanielGSoftware (3 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (2 commits)")[![danilopolani](https://avatars.githubusercontent.com/u/6277291?v=4)](https://github.com/danilopolani "danilopolani (1 commits)")[![daraghoshea](https://avatars.githubusercontent.com/u/1172998?v=4)](https://github.com/daraghoshea "daraghoshea (1 commits)")

---

Tags

data-transfer-objectlaravellaravel-packagevalue-objectValue Objectdata-transfer-objectjessarcherlaravel-castable-data-transfer-objectcastable-data-transfer-objectlaravel-castable-value-objectcastable-value-object

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jessarcher-laravel-castable-data-transfer-object/health.svg)

```
[![Health](https://phpackages.com/badges/jessarcher-laravel-castable-data-transfer-object/health.svg)](https://phpackages.com/packages/jessarcher-laravel-castable-data-transfer-object)
```

###  Alternatives

[moneyphp/money

PHP implementation of Fowler's Money pattern

4.8k82.5M422](/packages/moneyphp-money)[laragraph/utils

Utilities for using GraphQL with Laravel

2113.8M7](/packages/laragraph-utils)[keepsuit/laravel-temporal

Laravel temporal.io

4875.0k](/packages/keepsuit-laravel-temporal)[cerbero/dto

Data Transfer Object (DTO)

17119.4k1](/packages/cerbero-dto)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
