code16
Published in

code16

How to use the new PHP Enum in Laravel

Photo by Mick Haupt on Unsplash
<?php

namespace App\Enums;

enum BlogpostState: string
{
case DRAFT = 'state_draft';
case PUBLISHED = 'state_published';
}

Entity model

When creating your database schema, you can use eloquent’s“string” type for the state column as it will store the Enum’s backed value as a string: ‘state_draft’ or ‘state_published’.

public function up()
{
Schema::create('blogposts', function (Blueprint $table) {
...
$table->string('state');
});
}
<?php

namespace App\Models;
class Blogpost extends Model
{
protected $casts = [
'state' => BlogpostState::class,
];
}
>>> dd($blogpost->state);
=> App\Enums\BlogpostState {
+name: "DRAFT",
+value: "state_draft",
}
public function isPublished()
{
return $this->state === BlogpostState::PUBLISHED;
}
Blogpost::where('state', BlogpostState::PUBLISHED)->get();
>>> dd($blogpost->state->value);
=> "state_draft"
>>> $blogpost->update(['state' => 'state_foo']);                                                                                                                   PHP Error:  "state_foo" is not a valid backing value for enum "App\Models\Enums\BlogpostState"
    public function label(): string
{
return match($this)
{
self::DRAFT => 'Draft...',
self::PUBLISHED => 'Published!',
};
}
>>> $blogpost->state->label();
=> "Draft..."

Validation rule

When you want to make sure an input match an enum, you can use a new laravel rule:

<?php

namespace App\Http\Requests;
class BlogpostRequest extends FormRequest
{
public function rules()
{
return [
"state" => [
"required",
new Enum(BlogpostState::class)
],
];
}
}
This is the default validation message for an invalid Enum value

Factory

Also, when you want to seed a blogpost, you can now use enum directly in your factory:

<?php

namespace Database\Factories;

class BlogpostFactory extends Factory
{

public function definition()
{
return [
...
'state' => BlogpostState::DRAFT,
];
}
}

Route bindings

Since Laravel 9, there is now implicit route binding with enum. So you can type-hint your enum and Laravel will automatically cast the string value from the URL :

Route::get('/blog/{state}', function(BlogpostState $state) {
// here $state is an enum instance
});
  • https://mysite.com/blog/state_draft
  • https://mysite.com/blog/state_published

--

--

About open source projects at CODE 16

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store