Laravel Enums: A Comprehensive Guide

September 6, 2026

laravelEnumPHPbackendweb development

PHP introduced native Enums in PHP 8.1. Laravel later added strong support for Enums and enhanced that support with additional features.

What are Enums?

Enum is a special class that represents a fixed set of constants.

For example, Before we had to use custom classes to manage different states or types.

// Using class 
class PostStatus
{
    public const DRAFT = 'draft';
    public const PENDING = 'pending';
    public const PUBLISHED = 'published';
    public const ARCHIVED = 'archived';
}
 
// Using Enums
enum PostStatus: string
{
    case Draft = 'draft';
    case Pending = 'pending';
    case Published = 'published';
    case Archived = 'archived';
}
 
// Enum Usage
PostStatus::Draft->value; // draft
PostStatus::Draft->name; // Draft
 

Advantages of Enums

Enums has more advantages than using custom classes to manage different states or types. Some of the advantages are:

  1. Type Safety: Enum is own type that provides runtime type checking.
  2. Auto-completion: For Enums IDEs provides auto-completion for better developer experience. It also provides better code readability.
  3. Method Support: Enums can have methods, which allows you to add custom logic to the enum.
  4. Immutability: Enum cases are singleton instances. They don't have mutable properties.

Types of Enums

1. Backed Enums

Backed Enums are Enums that have a value of type string or int.

enum Status: string
{
    case Draft = 'draft';
    case Pending = 'pending';
    case Published = 'published';
    case Archived = 'archived';
}

2. Pure Enums

Pure Enums are Enums that do not have a value.

enum Status
{
    case Draft;
    case Pending;
    case Published;
    case Archived;
}

Using Enum in Laravel

Create Enum

php artisan make:enum PostStatus

This will create an Enum in the app/Enums directory.

Using Enum in Model

This is one of the most important uses of Enums in Laravel. Instead of using strings or integers to represent different states or types, we can use Enums.

    protected $casts = [
        'status' => PostStatus::class,
    ];

Using Enum in Controller

Use Enums in Controller similar to using custom classes.

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::where('status', PostStatus::Draft)->get();
        return view('posts.index', compact('posts'));
    }
}

Using Enum in View

Access Enums directly in the view if casted in the model.

@foreach ($posts as $post)
    <p>{{ $post->status?->value }}</p>
    <p>{{ $post->status?->name }}</p>
    <p>{{ $post->status?->label() }}</p>
@endforeach

Select Options

Enums provide cases() method that returns an array of all the cases in the enum.

 
enum PostStatus: string
{
    case Draft = 'draft';
    case Pending = 'pending';
    case Published = 'published';
    case Archived = 'archived';
 
    public function label(): string
    {
        return match ($this) {
            self::Draft => 'Draft',
            self::Pending => 'Pending',
            self::Published => 'Published',
            self::Archived => 'Archived',
        };
    }
}
 
// In model 
class Post extends Model {
    protected $casts = [
        'status' => PostStatus::class,
    ]; 
}
 
<select name="status" id="status">
    @foreach (PostStatus::cases() as $status)
        <option value="{{ $status->value }}" {{ $post->status === $status ? 'selected' : '' }}>{{ $status->label() }}</option>
    @endforeach
</select>

In Validation & Value Retrieval

You can also use Enums in validation to validate the enum values and convert to the enum instance.

{
    "status": "draft"
}
use Illuminate\Validation\Rule;
 
 
// validate the enum
$request->validate([
    'status' => ['required', Rule::enum(PostStatus::class)],
]);
 
// Get the validated value and convert into Enum instance
$status = $request->enum('status', PostStatus::class);

In Migrations

Enums can also be used in migrations to set default values.

Use backed enum with Eloquent to ensure that the database schema matches the enum values.

 
enum PostStatus: string
{
    case Draft = 'draft';
    case Pending = 'pending';
    case Published = 'published';
    case Archived = 'archived';
 
    public static function values(): array
    {
        return array_column(self::cases(), 'value');
    }
}
 
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->string('status')->default(PostStatus::Draft->value); // stores enum value 
    $table->timestamps();
});
 

For restrict the column to enum. But this requires database schema changes every time when the enum case changes.

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->enum('status', PostStatus::values())->default(PostStatus::Draft->value);
    $table->timestamps();
});

Methods in Enum

You can also add methods to Enums to add custom logic to the enum.

enum PostStatus: int
{
    case Draft = 0;
    case Pending = 1;
    case Published = 2;
    case Archived = 3;
 
    public function label(): string
    {
        return match ($this) {
            self::Draft => 'Draft',
            self::Pending => 'Pending',
            self::Published => 'Published',
            self::Archived => 'Archived',
        };
    }
}
 
// Usage
PostStatus::Draft->label(); // Draft

from() vs tryFrom()

Backed Enums gives two useful methods from() and tryFrom().

// Using from()
PostStatus::from(0); // PostStatus::Draft
 
// Using tryFrom()
PostStatus::tryFrom(0); // PostStatus::Draft
 
// Using tryFrom() with invalid value
PostStatus::tryFrom(4); // null
 
// Using from() with invalid value
PostStatus::from(4); // ValueError

cases() method

This method returns an array of all the cases in the enum.

 
enum PostStatus: int
{
    case Draft = 0;
    case Pending = 1;
    case Published = 2;
    case Archived = 3;
 
    public function label(): string
    {
        return match ($this) {
            self::Draft => 'Draft',
            self::Pending => 'Pending',
            self::Published => 'Published',
            self::Archived => 'Archived',
        };
    }
 
}
 
$cases = PostStatus::cases();
 
foreach ($cases as $case) {
    echo $case->value; // 0, 1, 2, 3
    echo $case->label(); // Draft, Pending, Published, Archived
}

Serialization of Enums

serialize() / unserialize()

PHP has serialize/unserialize support for enums.

enum PostStatus: int
{
    case Draft = 0;
    case Pending = 1;
    case Published = 2;
    case Archived = 3;
}
 
$serialized = serialize(PostStatus::Draft); // string
$unserialized = unserialize($serialized); // PostStatus::Draft
 
PostStatus::Draft === $unserialized; // true

jsonSerialize()

Enums can also be serialized to JSON using built in JsonSerializable interface.

use JsonSerializable;
 
enum PostStatus: int implements JsonSerializable
{
    case Draft = 0;
    case Pending = 1;
    case Published = 2;
    case Archived = 3;
 
    public function jsonSerialize(): mixed
    {
        return [
            'value' => $this->value,
            'name' => $this->name,
        ];
    }
}
 
// With jsonSerialize 
$serialized = json_encode(PostStatus::Draft); 
// "{"value":0,"name":"Draft"}" 
 
// Without jsonSerialize 
$serialized = json_encode(PostStatus::Draft); 
// "0" (It returns the value of the enum)

Translatable Enums

If you are working with multiple languages, you can translate with enums.

Language File:

// lang/en/post-status.php
return [
    'draft' => 'Draft',
    'pending' => 'Pending',
    'published' => 'Published',
    'archived' => 'Archived'
];
 
enum PostStatus: string
{
    case Draft = "draft";
    case Pending = "pending";
    case Published = "published";
    case Archived = "archived";
 
    public function label(): string
    {
        return __("post-status.{$this->value}");
    }
}
 
// Usage
PostStatus::Draft->label(); // Draft

const in enums

enum PostStatus: string
{
    case DRAFT = "draft";
    case PENDING = "pending";
    case PUBLISHED = "published";
    case ARCHIVED = "archived";
 
    public const DRAFT_STATUS = self::DRAFT->value;
}
 
// Usage
PostStatus::DRAFT_STATUS;

static method in Enum

enum PostStatus: int
{
    case Draft = 0;
    case Pending = 1;
    case Published = 2;
    case Archived = 3;
 
    public static function options(): array
    {
        return array_column(self::cases(), 'name', 'value');
    }
}
 
// Usage
PostStatus::options(); // [0 => "Draft", 1 => "Pending", 2 => "Published", 3 => "Archived"]

Advance Enum Features

Interfaces in Enums

You can implement any number of interfaces in enums.

interface HasLabel {
    public function label(): string;
}
 
enum PostStatus: string implements HasLabel
{
    case DRAFT = "draft";
    case PENDING = "pending";
    case PUBLISHED = "published";
    case ARCHIVED = "archived";
 
    public function label(): string
    {
        return match ($this) {
            self::DRAFT => 'Draft',
            self::PENDING => 'Pending',
            self::PUBLISHED => 'Published',
            self::ARCHIVED => 'Archived',
        };
    }
}

Traits in Enums

    trait HasCommonMethods {
 
        // works only for backed enums
        public static function values() : array {
            return array_column(self::cases(), 'value');
        }
        
        // works for both backed and pure enums
        public static function names(): array {
            return array_column(self::cases(), 'name');
        }
    }
 
    enum PostStatus: string {
        
        use HasCommonMethods;
 
        case DRAFT = 'draft';
        case PENDING = 'pending';
        case PUBLISHED = 'published';
        case ARCHIVED = 'archived';
    }
 
    // Usage
    PostStatus::values(); // ["draft", "pending", "published", "archived"]
    PostStatus::names(); // ["DRAFT", "PENDING", "PUBLISHED", "ARCHIVED"]

Using AsEnumCollection and AsEnumArrayObject

When database column contains multiple values of enum , use AsEnumCollection and AsEnumArrayObject.

suppose database column statuses that contains [1,2]

use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
 
enum PostStatus :int {
    case DRAFT = 1;
    case PENDING = 2;
    case PUBLISHED = 3;
    case ARCHIVED = 4;
}

AsEnumCollection

// In model
 class Post extends Model { 
 
    protected $casts = [
        'statuses' => AsEnumCollection::of(PostStatus::class),
    ]; 
 }
 
$post = Post::find(1);
 
$post->statuses; // collect([PostStatus::DRAFT, PostStatus::PENDING])
 
$post->statuses->contains(PostStatus::DRAFT);
 
$post->statuses->each(function(PostStatus $status){
    echo $status->name; // DRAFT , PENDING
    echo $status->value; // 1 , 2
});
 

AsEnumArrayObject

This is similar to AsEnumCollection but it returns an ArrayObject instead of a Collection.

// In model
 class Post extends Model { 
 
    protected $casts = [
        'statuses' => AsEnumArrayObject::of(PostStatus::class),
    ]; 
 }
 
$post = Post::find(1);
 
$post->statuses; // ArrayObject([PostStatus::DRAFT, PostStatus::PENDING])
 
$post->statuses[0]; // PostStatus::DRAFT
 
$post->statuses[] = PostStatus::ARCHIVED;
 
$post->statuses; // ArrayObject([PostStatus::DRAFT, PostStatus::PENDING, PostStatus::ARCHIVED])
 
$post->save();

Diffrence From Object

Enums are built on classes and objects, but still they do not support all object-related features.

  • Constructors and Destructors are not allowed.
  • Inheritance is not supported but may implement any number of interfaces.
  • static and instance properties not allowed.
  • Enum Case must be singleton instances.
  • Enums must be used after declaring them.
  • Public, private, and protected methods, static methods, and constants are allowed.

Conclusion

Enums are a great way to manage different states or types in your application. They provide type safety, auto-completion, and method support. They are also immutable, which makes them a good choice for managing different states or types in your application.