TL;DR
Long story short, don't reference your business layer within migration files.
Migrations should be immutable snapshots of your database history, never dependent on evolving application code.
❌ Bad (breaks if enum class changes or is removed)
$table->enum('role', array_column(Can::cases(), 'value'));
✅ Good (enum values explicitly defined, stable and independent)
$table->enum('role', ['access_admin', 'can_impersonate']);
Read the Full Thing
Often, when we define enum values in a model, like a role property or a status for something, and we want to provide an input where the user can choose an option, it's a good practice to reference the enum class by using foreach logic to iterate over these values to display them for the user.
Something like:
// app/Enums/Role.php
enum Role: string
{
case Admin = 'access_admin';
case Moderator = 'can_impersonate';
case User = 'regular_user';
}
{{-- resources/views/users/form.blade.php --}}
<select name="role">
@foreach(Role::cases() as $role)
<option value="{{ $role->value }}">
{{ str_replace('_', ' ', ucfirst($role->value)) }}
</option>
@endforeach
</select>
That's a good practice, isn't it? Can you imagine if, instead of iterating over an enum to get those values, you chose to rewrite the same occurrences in the whole project (backend, frontend)? Not cool.
Why Migrations Are Different
Migrations aren't like your application code - they're historical records of how your database evolved over time. Once a migration runs in production, it should never need to change.
Migrations should be your database changelog
- They document every schema change over time
- With dynamic references, you lose that documentation
- You can't look at migrations and understand how the schema evolved
Fragility
- Today: Your
Roleenum hasadminanduservalues - Migration runs: Creates column with those values, everything ok ✓
- 6 months later: You rename
Roleenum toUserRole, or delete it entirely - New developer runs migrations: 💥 Fatal error - Role class not found
As a result
- Forces us to edit old migrations
- Creates extra work
- Increases the risk of errors
Bonus
Also, I'd avoid using foreignIdFor() because it couples the migration directly to a model. If that model is deleted or renamed, the migration becomes invalid.
Well, that's all, folks.
Top comments (0)