php
52 lines · 8 steps
Layered config merging in PHP
A resolver folds any number of override layers onto defaults with a recursive deep merge and list deduplication.
Explained by
highlit
1final class ConfigResolver
2{
3 private array $merged;
4
5 public function __construct(array $defaults, array ...$overrides)
6 {
7 $this->merged = array_reduce(
8 $overrides,
9 fn (array $carry, array $layer): array => $this->deepMerge($carry, $layer),
10 $defaults
11 );
12 }
13
14 public function all(): array
15 {
16 return $this->merged;
17 }
18
19 private function deepMerge(array $base, array $layer): array
20 {
21 foreach ($layer as $key => $value) {
22 if (is_int($key)) {
23 $base[] = $value;
24 continue;
25 }
26
27 if (is_array($value) && isset($base[$key]) && is_array($base[$key])) {
28 $base[$key] = $this->deepMerge($base[$key], $value);
29 continue;
30 }
31
32 $base[$key] = $value;
33 }
34
35 return $this->dedupeLists($base);
36 }
37
38 private function dedupeLists(array $config): array
39 {
40 foreach ($config as $key => $value) {
41 if (!is_array($value)) {
42 continue;
43 }
44
45 $config[$key] = array_is_list($value)
46 ? array_values(array_unique($value, SORT_REGULAR))
47 : $this->dedupeLists($value);
48 }
49
50 return $config;
51 }
52}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Folding layers with array_reduce turns any number of overrides into one clean accumulation.
- 2Distinguishing integer keys from string keys lets one merge routine handle both lists and maps.
- 3Recursing into nested arrays keeps deep structures merged rather than blindly overwritten.
Related explainers
php
<?php namespace App\Models\Concerns;
Building soft deletes as an Eloquent trait in Laravel
traits
soft-delete
global-scope
Intermediate
10 steps
php
<?php namespace App\Services;
Idempotent role assignment in Laravel
many-to-many
pivot-data
idempotency
Intermediate
8 steps
php
<?php namespace App\Services;
Merging overlapping busy time blocks in PHP
interval-merging
sorting
datetime
Intermediate
8 steps
php
<?php namespace App\Listeners;
How event subscribers group listeners in Laravel
event-driven
subscribers
queues
Intermediate
6 steps
php
<?php namespace App\Services;
How user impersonation works in Laravel
authentication
authorization
session
Intermediate
8 steps
php
class OrderReceiptController extends Controller { public function store(Request $request, Order $order) {
Handling receipt uploads in a Laravel controller
file-upload
validation
authorization
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/layered-config-merging-in-php-explained-php-81f1/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.