Mastering Enums in Laravel: A Complete Guide with Practical Examples

Learn how to use enums in Laravel to simplify your code, improve validation, and manage fixed values efficiently. This complete guide covers practical examples, best practices, and tips to boost your Laravel development.

Introduction to Enums in Laravel

In many Laravel apps, we often use strings like 'pending' or 'approved' to represent statuses. The problem? It’s easy to mistype and hard to manage.

Enums solve this by letting you define a fixed set of values in a clean, readable way. With PHP 8.1+, enums are built-in, you can use them directly in forms, tables, route and validation — making your code safer and smarter.

Creating Enums in Laravel

Creating an enum in laravel is super easy. For example:

enum OrderStatus: string {
    case Pending = 'pending';
    case Shipping = "shipping";
    case Approved = 'approved';
    case Delivered = "delivered";
}

Now instead of using string everywhere, you use OrderStatus::Pending, which avoids mistake and also improves readability. The above enum and database type enum are completely different.

You may also have seen the real world projects where the roles are based on enum.

enum UserRole: string{
    case User = "user"; // or int like 0
    case Admin = "admin"; // or int like 1
    case SuperAdmin = "super_admin"; // or int like 2
}

Enum Casting

Laravel makes it easy to cast model attributes to enums. This means your database values automatically convert to enum instances when you access them, and back to strings (or integers) when saving.

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected $casts = [
        'status' => OrderStatus::class, // cast 'status' column to enum
    ];
}

Now, we can use them directly:

$order = Order::find(1);

if ($order->status === OrderStatus::Pending) {
    $order->status = OrderStatus::Approved;
    $order->save();
}

The label() Method in Enums

Sometimes, enum values are not user-friendly or you need to change their display name in UI. The label() method lets you define a human readable label for each case.

enum OrderStatus: string {
    case Pending = 'pending';
    case Shipping = "shipping";
    case Approved = 'approved';
    case Delivered = "delivered";

   public function label(): string
   {
        return match($this) {
            self::Pending => 'Pending Approval',
            self::Approved => 'Approved',
            self::Rejected => 'Rejected',
        };
    }
}
//Usage:
$status = OrderStatus::Pending;
echo $status->label(); // Pending Approval

// suppose this is used in Order Model
$order->status->label();

//in blade:
{{$order->status->label()}} 

Check out more about enum in php docs.

Validation with Enums in Laravel

Its super simple to validate the enum.

$request->validate([
    'status' => ['required', Rule::enum(OrderStatus::values())],
]);

//or only and except.
Rule::enum(OrderStatus::class)
    ->only([OrderStatus::Pending, OrderStatus::Approved]);
 
Rule::enum(OrderStatus::class)
    ->except([OrderStatus::Pending, OrderStatus::Approved]);

Now, above validation will check status upon our OrderStatus enum and only valid enum can be saved.

Implicit Enum Binding

Laravel allows you to automatically convert route parameters into enum instances, called implicit enum binding. This makes your controllers cleaner and ensures only valid enum values are passed.

use Illuminate\Support\Facades\Route;

Route::get('/orders/{status}', function (OrderStatus $status) {
    return "Selected status: " . $status->label();
});

Other useful methods

cases():

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

OrderStatus::cases();  
// Output: [OrderStatus::Pending, OrderStatus::Approved, OrderStatus::Rejected]

from($value)

  1. Gets the enum instance from a value. Throws an error if invalid.
$status = OrderStatus::from('approved');  
echo $status->name; // Approved

tryFrom($value)

  1. Similar to from(), but returns null if the value is invalid instead of throwing an error.
$status = OrderStatus::tryFrom('invalid');  
var_dump($status); // null

name()

  1. Returns the case name as declared in the enum.
$status = OrderStatus::Pending;  
echo $status->name; // Pending

Custom methods (like label() or color())

  1. You can define your own methods in the enum for UI or logic purposes.
public function label(): string { ... }  
public function color(): string { ... }

FAQ

Can enums be stored in the database?

Yes! You can store the enum’s value in a database column and use Laravel casting to automatically convert it to an enum instance.

How do I display user-friendly names for enums?

Define a label() method inside the enum:
public function label(): string { … }

Why should I use enums instead of strings?

Avoid typos and invalid values, Cleaner and more maintainable code, Works well with forms, tables, validation, and routes

What is enum casting?

Enum casting allows a model attribute to automatically convert to and from an enum:
protected $casts = [‘status’ => OrderStatus::class];

What is implicit enum binding?

Laravel can automatically convert route parameters to enum instances:
Route::get(‘/orders/{status}’, fn(OrderStatus $status) => $status->label());

ALSO READ:

Leave a Reply

Your email address will not be published. Required fields are marked *