Fluent Builder Pattern
debt(d7/e3/b3/t3)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' and the key misuse pattern — mutable builder state being shared/reused across tests or call sites — only manifests as unexpected object state at runtime or in test failures. PHPStan (the listed tool) can catch missing return types or wrong types but won't flag shared mutable builder state semantically. A human reviewer must notice the reuse pattern.
Closest to 'simple parameterised fix' (e3). The quick_fix describes returning a new immutable builder instance from each setter — a structural change to one builder class that affects all its setter methods. This is more than a one-line patch but stays within a single component/class, aligning with e3.
Closest to 'localised tax' (b3). The pattern applies broadly (web, cli, queue-worker) but each builder is self-contained. Misuse (mutable shared state) is a tax paid only by the components using that specific builder — the rest of the codebase is unaffected. Not load-bearing across the whole system.
Closest to 'minor surprise (one edge case)' (t3). The misconception listed is that fluent builders violate SRP, which is a conceptual misread rather than a behavioral trap. The common mistakes (forgetting $this return, no build() terminal) are well-documented gotchas that most PHP developers learn quickly. The shared mutable state trap is a real edge case but limited in scope.
Also Known As
TL;DR
Explanation
The Fluent Builder returns $this from each configuration method. Benefits: readable method chains, IDE autocomplete, avoids 10-parameter constructors. Fluent builders are self-contained. Used in: Eloquent query builder, PHPUnit mock builder, test data factories.
Common Misconception
Why It Matters
Common Mistakes
- Forgetting to return $this
- Fluent builder for 2-3 field objects
- No build() terminal method
Code Examples
$u = new User('Alice','alice@ex.com','admin',true,null,new DateTime(),null,[]);
$u = UserBuilder::new()->withName('Alice')->withEmail('alice@ex.com')->asAdmin()->build();