🛑 Stop me if you’ve faced this decision before.
You are writing a Laravel migration.
You need to add an optional column, like unit_type.
Not every product needs a unit.
So, you have two choices:
$table->string('unit_type')->default('');$table->string('unit_type')->nullable();
I almost always chose Option 1.
Why? Fear.
I was afraid of the dreaded Trying to access property on null error in my frontend.
I just wanted to output the value without writing if statements everywhere.
Using default('') felt "safe."
But after 10 years of database design, I realized I was doing it wrong.
Here is a simple way to look at it:
Imagine a warehouse shelf. 📦
Using `nullable()` is like having no box on the shelf.
It means: "This item does not apply here." (e.g., A digital download has no weight).
Using `default('')` is like putting an empty box on the shelf.
It means: "There is a box here, but we forgot to put something inside."
When you use empty strings, you are technically "lying" to your database. You are saying there is a value (text of length 0), even when there isn’t.
Why does this matter?
❌ Queries get messy: searching for WHERE column IS NULL is standard. Searching for WHERE column = '' feels amateur.
❌ Foreign Keys: You can’t make an empty string a foreign key later.
❌ Analytics: Reports get confused between "missing data" and "empty text."
The Best Practice Solution?
Keep the database clean, and handle the "safety" in your Model.
- In your migration, use
nullable(). Let the database be accurate. - In your Laravel Model, use an Accessor:
public function getUnitTypeAttribute($value)
{
return $value ?? '';
}
This gives you the best of both worlds.
Your database stores clean NULL values.
Your frontend gets a safe empty string.
👇 What’s your preference? Do you strictly enforce NULLs, or do you sneak in defaults to save time? Let’s argue in the comments.

Top comments (0)