Named Constructor Pattern
Also Known As
static factory method
factory method
named constructor
TL;DR
Static factory methods with descriptive names that replace overloaded constructors — making object creation intent clear when multiple creation paths exist.
Explanation
PHP constructors have a single name (__construct) and cannot be overloaded. Named constructors are static methods that communicate intent: Money::fromCents(500), Money::fromDollars(5.00), DateRange::lastMonth(), User::createGuest(). They can return different subtypes, enforce invariants, or accept different input formats. Combined with a private constructor, they become the only way to instantiate the class — enforcing all construction passes through validated paths.
Common Misconception
✗ Named constructors are just static methods — they communicate intent by name, enforce all construction through validated paths, and can return different subtypes, none of which constructors support.
Why It Matters
new Money(500, 'cents') vs Money::fromCents(500) — the named constructor makes the unit explicit and prevents the ambiguity that causes subtle currency calculation bugs.
Common Mistakes
- Not making the constructor private when named constructors are the intended API — both paths remain available.
- Named constructors that accept the same parameters as the constructor — adds verbosity without clarity.
- Omitting validation in named constructors — they are the perfect place to enforce class invariants.
- Using static methods for everything instead of identifying which cases genuinely need named constructors.
Code Examples
✗ Vulnerable
// Ambiguous constructor — is 500 cents or dollars?
class Money {
public function __construct(private int $amount, private string $currency) {}
}
new Money(500, 'USD'); // $500 or 500 cents? Who knows
✓ Fixed
// Named constructors — intent is explicit:
class Money {
private function __construct(
private readonly int $cents,
private readonly string $currency,
) {}
public static function fromCents(int $cents, string $currency): self {
if ($cents < 0) throw new InvalidArgumentException('Amount cannot be negative');
return new self($cents, $currency);
}
public static function fromDollars(float $dollars, string $currency): self {
return new self((int) round($dollars * 100), $currency);
}
public static function zero(string $currency): self {
return new self(0, $currency);
}
}
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
32
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Amazonbot 8
Google 5
Perplexity 3
Ahrefs 2
Unknown AI 2
Majestic 1
How they use it
crawler 21
Related categories
⚡
DEV INTEL
Tools & Severity
🟢 Low
⚙ Fix effort: Low
⚡ Quick Fix
Add static named constructors (Money::fromCents(500), Email::fromString('user@example.com')) to make object creation intent-clear and allow domain validation in the constructor
📦 Applies To
PHP 5.0+
web
cli
queue-worker
🔗 Prerequisites
🔍 Detection Hints
new Money(500, 'cents') — what does 500 mean? Named constructor makes it Money::fromCents(500)
Auto-detectable:
✗ No
phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: Low
Context: Class