Jose Jimenez
Jose Jimenez
Software Architect & Developer
> >

Using PHP 8.1 Enums in Laravel Models

Published in PHP, Laravel, Database on Jan 19, 2022

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 Model
10{
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 true
12echo $article1->status === StatusEnum::Draft;
13 
14// Returns false because it should be of StatusEnum::Open
15echo $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>