How to Use Enums in PHP and Laravel
Enums allow developers to represent a limited and well-defined set of options and improve code readability, maintainability, and type safety.
Laravel

Enums, short for "enumerations," are a powerful tool in programming for defining a set of named constants with fixed values. They allow developers to represent a limited and well-defined set of options and improve code readability, maintainability, and type safety. Although PHP lacked native support for enums until version 8.1, there were ways to implement them using libraries or custom classes. In this comprehensive tutorial, we'll cover both pre-PHP 8.1 and PHP 8.1+ approaches to defining and using enums in PHP and Laravel, with real-world examples.

 

Enums are best suited for constants in your code base that you do not have the need to store in the database but you have them in multiple places in your code. A good example can be checking if a user is an admin, author or a guest. A bad way to write this query can look like

 

User::where('user_type', 'admin')->get();

 

 

You do not need to directly type in the admin search key every where you need to check for this in the entire code base. If you have the need to change anything then you will need to change it everywhere you have checked for a user type. In cases where you have more than one developer working on the same project, code like this can be prone to bugs. Something as little as miss spelling the first letter of the word in caps can be hard to spot out. Always use Enum for constants like this.

 

Enum in Laravel

 

To use an Enum in laravel at the time of writing this post does not have an artisan command. You just need to create an Enum folder in the /App directory of your laravel application and create an Enum in there like so:

 

 
namespace App\Enum;

enum: string {
	case BEGINNER = 'beginner';
    case INTERMEDIATE = 'intermediate';
    case ADVANCE = 'advance';
}
 
 

Pre-PHP 8.1 Approach (Using Libraries)

 

Installation of Enum Library

 

Before PHP 8.1, PHP had no inbuilt support for enums so external packages and libraries were used to work with enums in PHP/Laravel projects. One such popular library is `spatie/enum`. Lets explore a bit on how to use this package. To use this package requires a composer installation using the composer command bellow

 
composer require spatie/enum

 

Creating an Enum Class using spatie/enum package

 

Next, we'll create an enum class that extends the Spatie\Enum\Enum class to define our custom enum. For example, we'll create a UserRole enum:

 
// app/Enums/UserRole.ph

namespace App\Enums;

use Spatie\Enum\Enum;

class UserRole extends Enum
{
    public static function admin(): UserRole
    {
        return new class () extends UserRole {
            public function getValue(): string
            {
                return 'admin';
            }
        };
    }

    public static function moderator(): UserRole
    {
        return new class () extends UserRole {
            public function getValue(): string
            {
                return 'moderator';
            }
        };
    }

    public static function user(): UserRole
    {
        return new class () extends UserRole {
            public function getValue(): string
            {
                return 'user';
            }
        };
    }
}
 

Using Enums in Laravel Models

 

Now, let's see how we can use our custom UserRole enum in a Laravel model:

 
 // app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Enums\UserRole;

class User extends Model
{
    // ...

    public function getRole(): UserRole
    {
        $roleValue = $this->getAttribute('role'); // Assuming 'role' column stores the role

        return UserRole::from($roleValue);
    }

    public function setRole(UserRole $role)
    {
        $this->setAttribute('role', $role->value);
    }
}

 
 

In this example, we have a User model that uses the UserRole enum to handle the role attribute. When retrieving the role from the database, we use the UserRole::from() method to convert the stored value into an instance of the UserRole enum. When setting the role, we use the value property of the enum instance to store the corresponding string value in the database.

 

 

Real-World Example: User Roles

 

 

Let's use the UserRole enum to implement user role-based authorization in Laravel.

 

 

 

// app/Http/Middleware/RoleMiddleware.php

namespace App\Http\Middleware;

use Closure;
use App\Enums\UserRole;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class RoleMiddleware
{
    public function handle(Request $request, Closure $next, string $role)
    {
        if (!Auth::check() || Auth::user()->getRole() !== UserRole::from($role)) {
            abort(403, 'Unauthorized.');
        }

        return $next($request);
    }
}

 

 

 

Here, we've created a middleware named RoleMiddleware that checks if the user has the required role to access specific routes. We use the UserRole enum to compare the user's role to the required role. If the user does not have the correct role, we return a 403 (Forbidden) response.

 

PHP 8.1+ Native Approach

 

Starting from PHP 8.1, native support for enums was introduced, eliminating the need for external libraries.

 

Creating an Enum Class

 

Let's create the UserRole enum using PHP 8.1+ native support:

 
 // app/Enums/UserRole.php

namespace App\Enums;

enum UserRole {
    case Admin;
    case Moderator;
    case User;
}

 
 

Defining enums in PHP 8.1+ is now more concise and clean.

 

Using Enums in Laravel Models

 

Using the UserRole enum in the User model remains the same, regardless of the PHP version:

 
 // app/Models/User.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Enums\UserRole;

class User extends Model
{
    // ...

    public function getRole(): UserRole
    {
        $roleValue = $this->getAttribute('role'); // Assuming 'role' column stores the role

        return UserRole::from($roleValue);
    }

    public function setRole(UserRole $role)
    {
        $this->setAttribute('role', $role);
    }
}

 
 

Real-World Example: Product Status

 

In this example, we'll use the ProductStatus enum to represent the different status of products in an e-commerce application.

 
// app/Enums/ProductStatus.php

namespace App\Enums;

enum ProductStatus {
    case Draft;
    case Active;
    case OutOfStock;
    case Discontinued;
}

 

In the Product model:

 
 

// app/Models/Product.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Enums\ProductStatus;

class Product extends Model
{
    // ...

    public function getStatus(): ProductStatus
    {
        $statusValue = $this->getAttribute('status'); // Assuming 'status' column stores the status

        return ProductStatus::from($statusValue);
    }

    public function setStatus(ProductStatus $status)
    {
        $this->setAttribute('status', $status);
    }
}
 
 

Conclusion

 

In this comprehensive tutorial, we explored the concept of enums in PHP and how to use them in Laravel. We covered two approaches: using a library for PHP versions before 8.1 and utilizing the native PHP 8.1+ enum feature. Enums are powerful tools for creating fixed sets of named constants, leading to more expressive, maintainable, and type-safe code.

Using enums in Laravel models allows for cleaner code and enhances readability and self-documentation. We demonstrated real-world examples of using enums for user roles, product status, and implementing role-based authorization.

Enums can greatly improve your code organization and help prevent bugs by enforcing a clear contract for possible values in your application. Whether you are working with PHP versions before 8.1 or leveraging the new native enum feature, incorporating enums into your Laravel project will undoubtedly enhance your development experience.

Author: moses on 06-08-2023
Related Posts
Subscribe to Our Mailing List
Built by codecontent.pro in partnership with Laraveldev.pro
© 2024 Laraveldev.pro