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.
You can install the package via composer:
composer require datomatic/laravel-enum-collections
The main parts of the package are:
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
)
EnumCollection
it's a one-dimensional collection that contains only enums.
You can create an enum collection in four different 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);
new EnumCollection($data, Enum::class);
The from
method throws a ValueError
exception if an element in $data
is incorrect, whereas tryFrom
skips invalid data without raising exceptions.
$data
can be a single element or a collection
, array
, or other iterable of elements.
If $data
contains only Enum elements, you can omit the EnumClass
(the collection will 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>
new EnumCollection([Enum::CASE1,Enum::CASE2]); // ✅ EnumCollection<Enum>
range
, median
, mode
, crossJoin
, flip
, collapse
, collapseWithKeys
, pluck
, mergeRecursive
, select
, flatten
, replaceRecursive
, sliding
, dot
, undot
, zip
map
, keys
, mapWithKeys
, combine
, mapToDictionary
, groupBy
, split
, splitIn
, chunk
, chunkWhile
, countBy
, toBase
containsAny
, doesntContainAny
, toValues
, toCollectionValues
, mapStrict
, mapWithKeysStrict
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
use \Datomatic\EnumCollections\EnumCollection;
$enumCollection = EnumCollection::from([Enum::CASE1,Enum::CASE2]); // [1,2]
$enumCollection->containsAny([Enum::CASE1,Enum::CASE3]); // true
$enumCollection->doesntContainAny(['PRIVATE','PUBLIC']); // true
The toValues
method serializes the collection content. If the element is a PureEnum
, it will return the name
of the case; otherwise, it will return 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]
You can cast a field to an EnumCollection
. To use this casting option, you need to configure the Eloquent Model properly.
Schema::table('table', function (Blueprint $table) {
$table->json('field_name')->nullable()->after('some_field');
});
To set up your model, you must:
- Add a custom cast
AsLaravelEnumCollection::class
with the enum class as an attribute. - Optionally, add the
HasEnumCollections
trait to enable querying on enum collection fields.
You can cast multiple fields if needed.
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),
];
}
}
When casting an enum collection field with the unique
modifier, the collection will automatically filter out any duplicate values. This ensures that only unique values are stored in the model.
To use the unique
modifier, you can set up your model as follows:
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.',true',
];
// Laravel 11
protected function casts(): array
{
return [
'field_name' => AsLaravelEnumCollection::of(FieldEnum::class, true),
];
}
}
When you set the enum collection field with repeated values, the duplicates will be removed:
$model = new TestModel();
$model->field_name = [FieldEnum::PRIVATE, FieldEnum::PUBLIC, FieldEnum::PRIVATE]; // ✅ EnumCollection<FieldEnum::PRIVATE, FieldEnum::PUBLIC>
$model->field_name = collect([FieldEnum::PRIVATE, FieldEnum::PUBLIC, FieldEnum::PRIVATE]); // ✅ EnumCollection<FieldEnum::PRIVATE, FieldEnum::PUBLIC>
The serialized enum collection saved in the database will contain only unique values, ensuring data integrity and preventing redundancy.
You can interact with the field_name
like a normal EnumCollection
, but it will always contain unique values:
$model = new TestModel();
$model->field_name = [FieldEnum::PRIVATE, FieldEnum::PUBLIC, FieldEnum::PRIVATE];
$model->field_name->contains(FieldEnum::PRIVATE); // true
$model->field_name->contains(FieldEnum::PROTECTED); // false
$model->field_name->toValues(); // [1, 2]
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>
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
.
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
If you include also the HasEnumCollections
into the model, you can query the models with the new where functions whereContains
, orWhereContains
, whereDoesntContain
, orWhereDoesntContain
,whereContainsAny
, orWhereContainsAny
, whereDoesntContainAny
and orWhereDoesntContainAny
.
TestModel::whereContains('field_name', FieldEnum::PRIVATE)->get()
TestModel::whereDoesntContain('field_name', FieldEnum::PRIVATE)->get()
TestModel::whereContainsAny('field_name', [FieldEnum::PRIVATE, FieldEnum::PUBLIC])->get()
TestModel::whereDoesntContainAny('field_name', [FieldEnum::PRIVATE, FieldEnum::PUBLIC])->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()
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.