PHPackages                             codewiser/casts - 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. codewiser/casts

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

codewiser/casts
===============

A set of casts for Laravel

v1.0.4(1y ago)0457MITPHPPHP ^8.1

Since Feb 28Pushed 1y ago2 watchersCompare

[ Source](https://github.com/C0deWiser/casts)[ Packagist](https://packagist.org/packages/codewiser/casts)[ RSS](/packages/codewiser-casts/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (6)Used By (0)

Custom Casts
============

[](#custom-casts)

Structures
----------

[](#structures)

Structure is an `array` or `json` attribute cast to an object.

For example:

```
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Casts\AsStringable;
use Illuminate\Support\Stringable;

/**
 * @property  null|Stringable  $first_name
 * @property  null|Stringable  $second_name
 * @property  null|Stringable  $family_name
 */
class Username extends Pivot
{
    protected function casts(): array
    {
        return [
            'first_name'  => AsStringable::class,
            'second_name' => AsStringable::class,
            'family_name' => AsStringable::class,
        ];
    }
}
```

> Note, that it is not a real Model. We use Pivot as it has no key and has attributes, casts etc. We will never save it. We use it just as structure interface.

Apply `Username` struct to `User` model:

```
use Codewiser\Casts\AsStruct;
use Illuminate\Database\Eloquent\Model;

/**
 * @property null|Username $name
 */
class User extends Model
{
    protected function casts(): array
    {
        return [
            'name' => AsStruct::using(Username::class)->nullable()
        ];
    }
}
```

Now, the IDE you are using may suggest structure attributes:

```
$user->name->first_name;
```

You can make it non-nullable. It means that `name` attribute will always be an object, even if empty.

```
use Codewiser\Casts\AsStruct;
use Illuminate\Database\Eloquent\Model;

/**
 * @property Username $name
 */
class User extends Model
{
    protected function casts(): array
    {
        return [
            'name' => AsStruct::using(Username::class)->required()
        ];
    }
}
```

> Structures may be nested.

Structure collections
---------------------

[](#structure-collections)

The same way you may cast collections of custom structs:

```
use Codewiser\Casts\AsStruct;
use Illuminate\Support\Collection;

/**
 * @property null|ContactCollection $contacts_1
 * @property null|Collection $contacts_2
 * @property Collection $contacts_3
 */
class User extends Model
{
    protected function casts(): array
    {
        return [
            'contacts_1' => AsStruct::collects(Contact::class, ContactCollection::class)->nullable(),
            'contacts_2' => AsStruct::collects(Contact::class)->nullable(),
            'contacts_3' => AsStruct::collects(Contact::class)->required(),
        ];
    }
}
```

Date-time with timezone
-----------------------

[](#date-time-with-timezone)

Laravel doesn't respect timezone. Cast `\Codewiser\Casts\AsDatetimeWithTZ` fixes this behaviour.

### Before

[](#before)

```
class Article extends \Illuminate\Database\Eloquent\Model
{
    protected $casts = [
        'date' => 'datetime'
    ];
}
```

```
// e.g. Laravel has Europe/London (+01:00) timezone
config()->set('app.timezone', 'Europe/London');

$model = new Article();

$model->date = '2000-01-01T10:00:00+02:00';

echo $model->date->format('c');
// Expecting 2000-01-01T09:00:00+01:00
// Actual    2000-01-01T10:00:00+01:00
```

### After

[](#after)

```
class Article extends \Illuminate\Database\Eloquent\Model
{
    protected $casts = [
        'date' => \Codewiser\Casts\AsDatetimeWithTZ::class
    ];
}
```

```
// e.g. Laravel has Europe/London (+01:00) timezone
config()->set('app.timezone', 'Europe/London');

$model = new Article();

$model->date = '2000-01-01T10:00:00+02:00';

echo $model->date->format('c');
// Expecting 2000-01-01T09:00:00+01:00
// Actual    2000-01-01T09:00:00+01:00
```

Request morph validator
-----------------------

[](#request-morph-validator)

### Before

[](#before-1)

```
use Illuminate\Database\Eloquent\Relations\Relation;

class MyRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'commentable_type' => 'required|string',
            'commentable_id'   => 'required',
        ];
    }

    public function getCommentable(): Model
    {
        $class = Relation::getMorphedModel($this->input('commentable_type'));

        return $class::find($this->integer('commentable_id'));
    }
}
```

### After

[](#after-1)

```
use Codewiser\Requests\HasMorphs;
use Illuminate\Database\Eloquent\Relations\Relation;

class MyRequest extends FormRequest
{
    use HasMorphs;

    public function rules(): array
    {
        return [
            ...$this->morph('commentable')
        ];
    }

    public function getCommentable(): Model
    {
        return $this->morphed('commentable');
    }
}
```

Additionally, you may pass list of classes, the morphed model could be.

```
use Codewiser\Requests\HasMorphs;
use Illuminate\Database\Eloquent\Relations\Relation;

class MyRequest extends FormRequest
{
    use HasMorphs;

    public function rules(): array
    {
        return [
            ...$this->nullableMorph('commentable', [Post::class, Article::class])
        ];
    }

    public function hasCommentable(): bool {
        return $this->hasMorph('commentable');
    }

    public function getCommentable(): ?Model
    {
        return $this->morphed('commentable');
    }
}
```

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance45

Moderate activity, may be stable

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~5 days

Total

5

Last Release

424d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ce23eaf7ae48d79d2b07efc83ff7cecb2664f428bd531b167b90169423f1453d?d=identicon)[Cellard](/maintainers/Cellard)

---

Top Contributors

[![Cellard](https://avatars.githubusercontent.com/u/1220316?v=4)](https://github.com/Cellard "Cellard (9 commits)")

---

Tags

castingdatetime-tzlaravelstructure

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/codewiser-casts/health.svg)

```
[![Health](https://phpackages.com/badges/codewiser-casts/health.svg)](https://phpackages.com/packages/codewiser-casts)
```

###  Alternatives

[wireui/wireui

TallStack components

1.8k1.3M16](/packages/wireui-wireui)[livewire/volt

An elegantly crafted functional API for Laravel Livewire.

4205.3M84](/packages/livewire-volt)[ramonrietdijk/livewire-tables

Dynamic tables for models with Laravel Livewire

21147.4k](/packages/ramonrietdijk-livewire-tables)

PHPackages © 2026

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