Extract Nested Closures into Private Methods for Maintainability

📖 2 minutes read

Laravel's collection fluent interface is powerful, but deeply nested closures quickly become unreadable. Here's when and how to refactor.

## The Problem: Triple-Nested Closures

“`php
return $dates->map(function($date) use ($variants, $allPricing, $defaults) {
return new DatePrice(
$variants->map(function($variant, $key) use ($date, $allPricing, $defaults) {
$match = $allPricing->filter(function($pricing) use ($date, $variant) {
return $pricing->date === $date && $pricing->variant === $variant;
})->first();
return $match?->price ?? $defaults[$key];
}),
$date
);
});
“`

This is doing too much in one statement:

1. Filtering pricing by date and variant
2. Falling back to default if not found
3. Mapping across all variants
4. Creating the final structure

## The Solution: Extract Inner Logic

Pull the innermost logic into a private method:

“`php
private function findPriceForVariantOnDate(
Collection $allPricing,
array $variant,
string $date,
?Price $defaultPrice
): ?Price {
return $allPricing
->filter(fn($p) => $p->date === $date && $p->matchesVariant($variant))
->first()?->price ?? $defaultPrice;
}
“`

Now the main logic becomes clear:

“`php
// Restructure: one DatePrice per date, containing prices for all variants
return $dates->map(function($date) use ($variants, $allPricing, $defaults) {
return new DatePrice(
$variants->mapWithKeys(function($variant, $key) use ($date, $allPricing, $defaults) {
$price = $this->findPriceForVariantOnDate(
$allPricing,
$variant,
$date,
$defaults[$key]
);
return [$key => $price];
}),
$date
);
});
“`

## When to Extract

**Extract when:**

– 3+ levels of nesting
– Inner logic is reused elsewhere
– The closure has complex conditionals
– You need to unit test the inner logic separately

**Keep inline when:**

– 1-2 levels of nesting with simple operations
– The closure is very short (1-2 lines)
– Extraction would require passing 5+ parameters

## Naming Matters

The extracted method name should read like documentation:

– `findPriceForVariantOnDate()` – immediately clear what it does
– `matchesVariant()` – better than `in_array($variant, $pricing->variants)`
– `getDefaultPrices()` – better than `$fallbacks`

Future developers (including you) will thank you.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *