The Enum
trait is a really useful way to allow you to pre-define all of the valid values for a given field on a model and enforce that their values are set appropriately. This basically allows you to treat a field as a menu without the database overhead of dealing with true enum fields or lookup tables.
namespace App;
use App\Traits\Enums;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Enums;
...
}
Model App\Post
has an enumerated field called status
that we want to enforce specific values for.
class Post extends Model
{
use Enums;
// Define all of the valid options in an array as a protected property that
// starts with 'enum' followed by the plural studly cased field name
protected $enumStatuses = [
'Draft',
'Scheduled',
'Published',
'Archived'
];
// Alternately, if you use an associative array, the keys can be used
// to set the value as well. The full string will still be stored in the database.
/* protected $enumStatuses = [
'dr' => 'Draft',
'sc' => 'Scheduled',
'pu' => 'Published',
'ar' => 'Archived'
]; */
...
Once you've defined this $enum
property on the model, any time that field is set on any instance, a validation process will run to enforce that the value is being set properly:
$post = new App\Post;
$post->status = 'Something Invalid';
// Throws an InvalidEnumException
$post = App\Post::first();
$post->status = 'Draft';
// Sets the value to Draft as expected
// Key values will always work to set the value as well,
// so using the non-associative array example, this will set status to 'Draft'
$post = App\Post::create([
'status' => 0
]);
// Using the associative array example, this will set status to 'Published'
$post = App\Post::create([
'status' => 'pu'
]);
Enumerations work really well in blade files too. Simply use the getEnum
static helper:
@foreach( App\Post::getEnum('status') as $key => $value)
{{ $key }}: {{ $value }}
@endforeach
Or use them with the LaravelCollective form builder:
{{ Form::select('status', App\Post::getEnum('status')) }}
Wow I totally forgot this gist existed.
I've since added this trait to a small collection of others, which you can find here: https://gitlab.com/two-thirds/eloquent-traits
@vsharper, I'm pretty sure you're missing the point here. Using a separate class with a bunch of consts ( consteses? consti? ) enforces absolutely nothing when the attribute is set or changed. I could still set 'status' to 'potato' and that abstract class isn't gonna stop it. And to make matters worse, you've added this completely separate file for an array of values that has absolutely no ties back to the model it pertains to.
The whole point in using this trait is that there is at least some level of enforcement when data is shoved into a new model.
@anthonygore thanks for the feedback. There newer version listed above has a
getSelectEnum
method that does just what you're looking for.