Using PHP 8.1 Enums in Laravel Models
The release of PHP 8.1 brings proper built-in support for Enums, proper cast support was also added in a pull request for Laravel 8. In this tutorial we will go over how to add Enums in Laravel Models. A more detailed article on Enums can be found on stitcher.io.
For this excercise we will have an Article model, with an Enum that will handle the article status
(closed|open|draft).
Storing Enum as string/integer/enum
Storing the value of your Enum in the database will highly depend on what you want for readability and performance. For a highly utilized column I will often times use TinyInt, if I need to have readability I will use a Varchar. I typically avoid the Enum column due experience and a few articles I've read over the years like this one. However that is out of scope for this article, you should find the column type that best suits your needs.
For my example I will be using varchar for my column to more easily be able to see my results.
Enum
For application consistency I created an app\Enum\{Model}
directory to more easily keep track of my Enums, I will also suffix my Enum file with Enum to more easily find it during autocomplete.
app/Enum/Article/StatusEnum.php
1<?php 2 3namespace App\Enum\Article; 4 5enum StatusEnum: string 6{ 7 case Closed = 'closed'; 8 case Open = 'open'; 9 case Draft = 'draft';10}
Migration
1Schema::create('article', function (Blueprint $table) {2 $table->string('status', 6);3});
Model
app/Models/Article.php
1<?php 2 3namespace App\Models; 4 5use App\Enum\Article\StatusEnum; 6use Illuminate\Database\Eloquent\Factories\HasFactory; 7use Illuminate\Database\Eloquent\Model; 8 9class Article extends Model10{11 use HasFactory;12 13 protected $casts = [14 'status' => StatusEnum::class,15 ];16}
Real World Usage
1$article1 = Article::create([ 2 'title' => 'My Draft Article', 3 'status' => StatusEnum::Draft, 4]); 5 6$article2 = Article::create([ 7 'title' => 'My Open Article', 8 'status' => StatusEnum::Open, 9]);10 11// Returns true12echo $article1->status === StatusEnum::Draft;13 14// Returns false because it should be of StatusEnum::Open15echo $article2->status === StatusEnum::Closed;
If we took a look at the records in our database we would see this:
Generating HTML fields
One additional benefit is that you can use StatusEnum::cases()
method to help generate a select dropdown to dynamically control your input fields moving forward.
1<select name="status" id="status"> 2@foreach(\App\Enum\Article\StatusEnum::cases() as $status) 3 <option value="{{ $status->value }}">{{ $status->name }}</option> 4@endforeach 5</select> 6 7// Will generate 8 9<select name="status" id="status">10 <option value="closed">Closed</option>11 <option value="open">Open</option>12 <option value="draft">Draft</option>13</select>