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!