Skip to content

datomatic/laravel-enum-collections

Repository files navigation

Enum Helper-DarkEnum Helper-Light

Laravel Enum Collections

Latest Version on Packagist Pest Tests number GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

A Laravel collection extension to store enums with a useful eloquent field cast and a helper trait.
Take your interaction with enums to the next level.
Compatible with PureEnum, BackedEnum and datomatic/laravel-enum-helper package.

Installation

You can install the package via composer:

composer require datomatic/laravel-enum-collections

The main parts of the package are:

EnumCollection

EnumCollection is an extension of base Laravel collection that expand his functionalities to add the compatibility with:

  • enum object instance
  • enum case name string
  • enum case value (only for BackedEnum)
  • enum case (string) value (only for IntBackedEnum)

Creating an EnumCollection

You can make enum collection in 4 ways:

use \Datomatic\EnumCollections\EnumCollection;

EnumCollection::of(Enum::class)->from($data);
EnumCollection::of(Enum::class)->tryFrom($data);
EnumCollection::from($data, Enum::class);
EnumCollection::tryFrom($data, Enum::class);

from method throw an ValueError Exception if an element in $data is wrong, instead tryFrom skips bad data without raise exceptions.
$data can be a single element or a collection, array,... of elements.

If $data contains only Enum elements you can also omit the EnumClass (the collection take the EnumClass of the first element).

EnumCollection::from(Enum::CASE1); // ✅ EnumCollection<Enum::CASE1>
EnumCollection::from('CASE1', Enum::class); // ✅ EnumCollection<Enum::CASE1>
EnumCollection::from(1, Enum::class); // ✅ EnumCollection<Enum::CASE1>
EnumCollection::from('1', Enum::class); // ✅ EnumCollection<Enum::CASE1>
EnumCollection::from([Enum::CASE1,Enum::CASE2]); // ✅ EnumCollection<Enum>
EnumCollection::from(collect([Enum::CASE1,Enum::CASE2])); // ✅ EnumCollection<Enum>

Contains method

use \Datomatic\EnumCollections\EnumCollection;

$enumCollection = EnumCollection::from([Enum::CASE1,Enum::CASE2]); // [1,2]

$enumCollection->contains(Enum::CASE1); // true
$enumCollection->contains(Enum::CASE3); // false
$enumCollection->doesntContain(Enum::CASE3); // true
$enumCollection->contains(1); // true
$enumCollection->contains('1'); // true
$enumCollection->contains('PRIVATE'); // true
$enumCollection->doesntContain('PRIVATE'); // false

toValues method

toValues method serialize the collection content, if the element is a PureEnum will be pass the name of the case, otherwise the value.

use \Datomatic\EnumCollections\EnumCollection;

EnumCollection::from([Enum::CASE1,Enum::CASE2,Enum::CASE2])->toValues(); // [1,2,2]
EnumCollection::from(['CASE1','CASE2','CASE2'],Enum::class)->toValues(); // [1,2,2]
EnumCollection::from([1,2,2],Enum::class)->toValues(); // [1,2,2]
EnumCollection::from(['1','2','2'],Enum::class)->toValues(); // [1,2,2]

Casting

You can cast a field to be an EnumCollection. To use this casting option, you need to set the Eloquent Model properly.

1. Database Migration

Schema::table('table', function (Blueprint $table) {
    $table->json('field_name')->nullable()->after('some_field');
});

2. Model set up

To set up your model you must:

  • add a custom cast AsLaravelEnumCollection::class with the enumClass as attribute
  • add an optional HasEnumCollections trait to make query on enum collections fields

You can also cast more than one field if you need.

use Datomatic\EnumCollections\Casts\AsLaravelEnumCollection;
use Datomatic\EnumCollections\EnumCollection;
use Illuminate\Database\Eloquent\Model;

class TestModel extends Model
{
    use HasEnumCollections;
    
    //Laravel 9/10
    protected $casts = [
        'field_name' => AsLaravelEnumCollection::class.':'.FieldEnum::class,
    ];
    
    //Laravel 11
    protected function casts(): array
    {
        return [
            'field_name' => AsLaravelEnumCollection::of(FieldEnum::class),
        ];
    }
}

Set the enum collection field

You can set enum collection field passing a single element, a collection or an array of elements. After the field will become an EnumCollection.

enum FieldEnum: int
{
    case PRIVATE = 1;
    case PUBLIC = 2;
    case PROTECTED = 3;
}

$model = new TestModel();
$model->field_name = FieldEnum::PRIVATE; // ✅ EnumCollection<FieldEnum::PRIVATE>
$model->field_name = 'PRIVATE'; // ✅ EnumCollection<FieldEnum::PRIVATE>
$model->field_name = 1; // ✅ EnumCollection<FieldEnum::PRIVATE>
$model->field_name = '1'; // ✅ EnumCollection<FieldEnum::PRIVATE>
$model->field_name = [FieldEnum::PRIVATE,FieldEnum::PUBLIC]; // ✅ EnumCollection<FieldEnum>
$model->field_name = collect([FieldEnum::PRIVATE,FieldEnum::PUBLIC]); // ✅ EnumCollection<FieldEnum>

Database saved data

A serialization of enumCollection is saved in the database, if the element is a PureEnum will be saved the name of the case, otherwise the value.

EnumCollection

Thanks to casting you can interact with field_name like a normal EnumCollection with all functionalities showed before.

$model = new TestModel();
$model->field_name = [FieldEnum::PRIVATE,FieldEnum::PUBLIC];

$model->field_name->contains(FieldEnum::PRIVATE); // true
$model->field_name->contains(FieldEnum::PROTECTED); // false
$model->field_name->contains(1); // true
$model->field_name->contains('1'); // true
$model->field_name->contains('PRIVATE'); // true
$model->field_name->doesntContain('PRIVATE'); // false
$model->field_name->doesntContain(FieldEnum::PROTECTED); // true

HasEnumCollections trait

If you include also the HasEnumCollections into the model, you can query the models with the new where functions whereContains, orWhereContains, whereDoesntContain and orWhereDoesntContain.

TestModel::whereContains('field_name', FieldEnum::PRIVATE)->get()
TestModel::whereDoesntContain('field_name', FieldEnum::PRIVATE)->get()

TestModel::whereContains('field_name', 1)
    ->whereContains('field_name', FieldEnum::PUBLIC)
    ->get()
    
TestModel::whereContains('field_name', [FieldEnum::PRIVATE,FieldEnum::PUBLIC])
    ->get()
TestModel::whereContains('field_name', collect([FieldEnum::PRIVATE,FieldEnum::PUBLIC]))
    ->get()
 TestModel::whereContains('field_name', EnumCollection::make([FieldEnum::PRIVATE,FieldEnum::PUBLIC]))
    ->get()
    
TestModel::whereContains('field_name', [1,2])
    ->get()

TestModel::whereContains('field_name', FieldEnum::PRIVATE)
    ->orWhereContains('field_name', FieldEnum::PUBLIC)
    ->get()

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.