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
<?php
namespace App\Enum\Article;
enum StatusEnum: string
{
case Closed = 'closed';
case Open = 'open';
case Draft = 'draft';
}
Migration
Schema::create('article', function (Blueprint $table) {
$table->string('status', 6);
});
Model
app/Models/Article.php
<?php
namespace App\Models;
use App\Enum\Article\StatusEnum;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $casts = [
'status' => StatusEnum::class,
];
}
Real World Usage
$article1 = Article::create([
'title' => 'My Draft Article',
'status' => StatusEnum::Draft,
]);
$article2 = Article::create([
'title' => 'My Open Article',
'status' => StatusEnum::Open,
]);
// Returns true
echo $article1->status === StatusEnum::Draft;
// Returns false because it should be of StatusEnum::Open
echo $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.
<select name="status" id="status">
@foreach(\App\Enum\Article\StatusEnum::cases() as $status)
<option value="{{ $status->value }}">{{ $status->name }}</option>
@endforeach
</select>
// Will generate
<select name="status" id="status">
<option value="closed">Closed</option>
<option value="open">Open</option>
<option value="draft">Draft</option>
</select>