Search by

codewiser / casts

Cellard

Object casting, enum collection, morph validator for Laravel

Package info

github.com/C0deWiser/casts

pkg:composer/codewiser/casts

Statistics

Installs: 569

Dependents: 0

Suggesters: 2

Stars: 0

Open Issues: 0

v1.1.2 2026-09-17 21:16 UTC

This package is auto-updated.

Last update: 2026-09-17 21:17:19 UTC


README

Object Casting

Just like Laravel allows to cast data to a Collection, it allows to cast data into an object.

use App\Collections\OptionCollection;
use Codewiser\Casts\AsObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;

/**
 * Get the attributes that should be cast.
 *
 * @return array<string, string>
 */
protected function casts(): array
{
    return [
        'option'  => AsObject::of(Option::class),
        'options' => AsCollection::using(OptionCollection::class, Option::class),
    ];
}

Enum Collections

Laravel provides AsEnumCollection to cast array of enum values into a collection, but actually it is REDUNDANT. It is more than enough to use AsCollection:of(Enum:class).

Much worse, that base collection can't handle enum values in some cases. For example, intersect or diff fails, as array_intersect doesn't support enums.

This package provides enum collection, where these methods are fixed to work with enums.

You may cast enum collection this way:

use App\Collections\OptionCollection;
use Codewiser\Collections\EnumCollection;
use Illuminate\Database\Eloquent\Casts\AsCollection;

/**
 * Get the attributes that should be cast.
 *
 * @return array<string, string>
 */
protected function casts(): array
{
    return [
        'roles' => AsCollection::using(EnumCollection::class, RoleEnum::class),
    ];
}

Date-time with timezone Casting

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

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

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

Form Request morph Validator

Before

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

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(): null|Post|Article 
    {
        return $this->morphed('commentable');
    }
}