GitHub LinkedIn
Profile Portfolio Blog

Apr 01, 2025

Supercharge your Enums in Laravel

What are Enums and why should you use them?

Enums provide a way to define a group of related values essentially becoming a self-contained "box of constants". The feature was introduced in PHP 8.1 so it has been around for a while now.

Before Enums, you'd often resort to constants for this kind of data. Imagine your website had user types e.g. Newbie, User, Moderator and Admin. Assuming you had a class for your User model, you could do something like this:

1class User
2{
3 const NEWBIE_TYPE = 'newbie';
4 const USER_TYPE = 'user';
5 const MOD_TYPE = 'moderator';
6 const ADMIN_TYPE = 'admin';
7}

By using Enums, you can extract these to its own file and that would look like this:

1enum UserType: string
2{
3 case NEWBIE = 'newbie';
4 case USER = 'user';
5 case MOD = 'moderator';
6 case ADMIN = 'admin';
7}

Which you can then access like so:

1$value = UserType::ADMIN->value; // admin

If you're not familiar with Enums then this will probably seem like only a slight improvement. But Enums come with a whole bag full of features.

Enums can also have their own methods which opens up so many possibilities. e.g. you can add any kind of helper methods to your Enum like this:

1public function label(): string
2{
3 return match ($this) {
4 self::NEWBIE = 'Newbie';
5 self::USER = 'User';
6 self::MOD = 'Moderator';
7 self::ADMIN = 'Administrator';
8 default => 'Undefined',
9 };
10}

And then access it like this:

1$label = UserType::MOD->label(); // Moderator

You can also easily loop through them by using the built in method cases() if you need to, for instance, display a dropdown with all the available options.

1<select name="user_type">
2 @foreach(UserType::cases() as $userType)
3 <option value="{{ $userType->value }}">
4 {{ $userType->label() }}
5 </option>
6 @endforeach
7</select>

Using Enums in Laravel

Enums are a PHP feature so you can use it anywhere you want whether you're using a framework or not. As you may expect though, Laravel does come with a few features of its own that take advantage of Enums, my favourite one being the use of it in validation. For instance, if you're validating the dropdown above, you can easily do it like so and Laravel will check if the provided option matches a valid enum value.

1use App\Enums\UserType;
2use Illuminate\Validation\Rule;
3 
4$request->validate([
5 'user_type' => [Rule::enum(UserType::class)],
6]);

Create your own artisan command to generate Enums

If you're like me and you're constantly creating new enums in your projects, then having a dedicated script to automate things might be worth it. Laravel allows you to create your own artisan commands and you can even make it look like one of its native commands, if you're feeling fancy.

Our custom artisan command is going to generate an Enum file for us but to do that, it needs a template so we'll have to create one first; so we'll create it as stubs/enum.stub, in the project root directory. If you decide to customise Laravel's own make commands, this is where those stubs will be published so this is the perfect place to do it.

1<?php
2 
3namespace App\Enums;
4 
5enum {{ name }}: string
6{
7 case TEST = 'test';
8 
9 /**
10 * @return string
11 */
12 public function label(): string
13 {
14 return match ($this) {
15 self::TEST => 'Test',
16 };
17 }
18 
19 /**
20 * Always remember to use this method instead of the default cases() as this will allow you
21 * to filter out the cases you don't want to show in the frontend while still keeping them
22 *
23 * @return {{ name }}[]
24 */
25 public static function all(): array
26 {
27 return [
28 self::TEST,
29 ];
30 }
31}

This is just a simple template but you can customise it as much as you want. e.g. I always like to have an all() method available where I return only the constants being actively used in the project as opposed to using the built in method cases() which returns every single constant in the Enum. This can be very useful in case you need to deprecate one of the constants and filter those out in a user facing page, for instance, as all you have to do is to remove it from the all method and no other code changes are needed.

Now that we have our stub, it's time to create the actual script. So we'll run this to create our own command and we'll call it MakeEnum;

1php artisan make:command MakeEnum

Running this command will generate a new class named MakeEnum in app\Console\Commands which you can then customise like so.

1<?php
2 
3namespace App\Console\Commands;
4 
5use Illuminate\Console\Command;
6use Illuminate\Filesystem\Filesystem;
7 
8class MakeEnum extends Command
9{
10 /**
11 * The name and signature of the console command.
12 *
13 * @var string
14 */
15 protected $signature = 'make:enum {name}';
16 
17 /**
18 * The console command description.
19 *
20 * @var string
21 */
22 protected $description = 'Make an Enum file';
23 
24 /**
25 * @var Filesystem
26 */
27 protected Filesystem $files;
28 
29 public function __construct(Filesystem $files)
30 {
31 parent::__construct();
32 
33 $this->files = $files;
34 }
35 
36 /**
37 * Execute the console command.
38 */
39 public function handle(): void
40 {
41 $path = base_path('App\\Enums\\'.$this->argument('name').'.php');
42 
43 $contents = $this->getSourceFile();
44 
45 if (! $this->files->exists($path)) {
46 $this->files->put($path, $contents);
47 $this->info("File : {$path} created");
48 } else {
49 $this->info("File : {$path} already exists");
50 }
51 }
52 
53 /**
54 * Get the stub path and the stub variables
55 *
56 * @return string|array|bool
57 */
58 public function getSourceFile(): string|array|bool
59 {
60 return $this->getStubContents(
61 __DIR__.'/../../../stubs/enum.stub',
62 [
63 'name' => $this->argument('name'),
64 ]
65 );
66 }
67 
68 /**
69 * Replace the stub variables(key) with the desire value
70 *
71 * @param $stub
72 * @param array $stubVariables
73 * @return string|array|bool
74 */
75 public function getStubContents($stub, array $stubVariables = []): string|array|bool
76 {
77 $contents = file_get_contents($stub);
78 
79 foreach ($stubVariables as $search => $replace) {
80 $contents = str_replace('{{ '.$search.' }}', $replace, $contents);
81 }
82 
83 return $contents;
84 }
85}

NOTE: If you wish to place your custom command somewhere else then you'll have to register it manually by doing this.

And there you have it! From now on, you can simply run php artisan make:enum MyAwesomeEnum and you'll have your brand new Enum waiting for you.

*Code highlighting provided by Torchlight.

© Antonio Lima, 2025.