Schema migrations are easy to plan and hard to deploy β especially when a column rename or consolidation touches dozens of call sites across the codebase. Here’s a trick I’ve used to make incremental migrations way less painful.
The Scenario
Imagine you have a model with numbered columns: price_1, price_2, all the way through price_60. A past design decision that seemed reasonable at the time but now just wastes space. You want to consolidate everything down to price_1.
The data migration is straightforward β copy the canonical value into price_1 for every row. But the scary part is all the existing code that reads $record->price_5 or $record->price_23 scattered across the app.
The Trick: Override getAttribute()
Instead of finding and updating every reference before deploying, override Eloquent’s getAttribute() to silently redirect old column access to the new consolidated column:
class PricingRecord extends Model
{
public function getAttribute($key)
{
$consolidatedPrefixes = [
'price_',
'cost_',
'fee_',
];
foreach ($consolidatedPrefixes as $prefix) {
if (preg_match('/^' . preg_quote($prefix) . '\d+/', $key)
&& $key !== $prefix . '1') {
// Redirect any tier N access to tier 1
return parent::getAttribute($prefix . '1');
}
}
return parent::getAttribute($key);
}
}
The Deployment Sequence
- Run the data migration β consolidate all values into the
_1columns - Deploy the
getAttribute()override β old code reading$record->price_5transparently getsprice_1 - Clean up call sites at your own pace β update references one PR at a time, no rush
- Remove the override once all references point to
_1 - Drop the old columns in a final migration
No big-bang refactor. No merge conflicts from a 40-file PR. No “please don’t deploy anything until my branch lands.”
One Caveat
This adds a regex check on every attribute access for that model. For a model you load a few times per request, it’s negligible. But if you’re hydrating thousands of records in a loop, profile it first. The regex is cheap, but “cheap Γ 10,000” can add up.
For most real-world use cases though, this buys you a safe, incremental migration path with zero downtime and zero broken features.

Leave a Reply