Let's discuss Enums in Laravel. Although there are numerous tutorials on how to use enums in Laravel and how to validate them, today I'd like to talk about something I discovered while using enums.

As a Maldivian, I frequently need to display enum values in my locale language, and enums do not support this out of the box. Allow me to demonstrate how I resolved this problem.

For the context of this article, we'll be using a Post model. Let's create a post migration with the following code (most of the fields have been removed for clarity).

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content')->nullable();
    $table->string('status');
    $table->timestamps();
});

Now let's create an enum for the status. You can place them wherever you like, but I usually put them in the app/Support/Enums directory.

enum PostStatuses: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
}

Now let's update the post model to use the enum.

class Post extends Model
{
    protected $casts = [
        'status' => PostStatuses::class
    ];
}

If I create a post and call $post->status, it will now return a PostStatuses instance. However, even if I add the translation for draft and published to the lang file and change the app locale, it will not display the translation. Therefore, I started adding an options method for every enum with translatable strings.

enum PostStatuses: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';

    public static function options(): array
    {
        return [
            self::DRAFT->value => __('Draft'), 
            self::PUBLISHED->value => __('Published'), 
        ];
    }
}

This allows me to easily fetch the translatable string as shown below.

\App\Support\Enums\PostStatuses::options()[$post->status->value];

I can further simplify this and add it as a method to the enum class.

public function getLabel(): string
{
    return self::options()[$this->value];
}

As a result, I can now get the translatable string value by simply calling getLabel() on the status as shown below.

$post->status->getLabel();

This will work, but let me show you what my final implementation looks like.

// Enum
enum PostStatuses: string implements Translatable
{

    use HasTranslatableLabels;
    
    case DRAFT = 'draft';
    case PUBLISHED = 'published';

    public static function options(): array
    {
        return [
            self::DRAFT->value => __('Draft'),
            self::PUBLISHED->value => __('Published'),
        ];
    }

}
// Enum Interface
interface Translatable
{

    public static function options(): array;

    public function getLabel(): string;

}
// Enum Trait
trait HasTranslatableLabels
{

    public function getLabel(): string
    {
        return self::options()[$this->value];
    }

}

If you have any ideas or thoughts about this article, feel free to leave a comment on my Twitter post. Thanks for reading, and have a great day!