← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Specification Pattern

architecture PHP 5.0+ Intermediate

Also Known As

specification business rule encapsulation composable criteria

TL;DR

Encapsulating business rules as composable objects that evaluate whether a candidate satisfies them — separating rules from entity code.

Explanation

The Specification pattern encapsulates a business rule as a class with an isSatisfiedBy($candidate): bool method. Specifications are composable: AndSpecification, OrSpecification, NotSpecification combine them with boolean logic. Example: ActiveCustomerSpecification->and(HasValidEmailSpecification) produces a compound rule. Benefits: business rules are named, reusable, and testable in isolation; they can be translated to query criteria (Doctrine Criteria or SQL WHERE clauses) for database-side filtering. PHP libraries: beberlei/specification, or implement the interface yourself (typically 10 lines). The pattern shines when the same rule must filter both in-memory collections and database queries — a Doctrine-aware specification generates DQL expressions while the core logic remains testable without a database.

Common Misconception

The specification pattern is just a fancy way to write WHERE clauses. Specifications encapsulate business rules as composable, reusable objects — they can be combined with and/or/not, used in both queries and in-memory filtering, and named to express domain concepts explicitly.

Why It Matters

The Specification pattern encapsulates business rules as composable objects — complex query conditions become named, testable, reusable specifications rather than SQL fragments scattered across repositories.

Common Mistakes

  • Specifications that leak SQL — they should express business rules, not WHERE clauses.
  • Not making specifications composable with AND, OR, NOT — the pattern's core value is composition.
  • Over-using specifications for simple, single-use queries — a repository method is simpler.
  • Specifications that perform I/O — they should be pure predicates, not data fetchers.

Code Examples

✗ Vulnerable
// Raw conditions scattered in repository:
public function findEligibleCustomers(): array {
    return $this->db->query(
        'SELECT * FROM customers WHERE active = 1 AND balance > 100 AND age >= 18'
    )->fetchAll();
}
// 'Eligible' means different things in different contexts — use a specification:
// $eligible = new ActiveSpec()->and(new MinBalanceSpec(100))->and(new AdultSpec());
✓ Fixed
interface Specification {
    public function isSatisfiedBy(mixed $candidate): bool;
}

class ActiveCustomer implements Specification {
    public function isSatisfiedBy(mixed $customer): bool {
        return $customer->isActive() && !$customer->isBanned();
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 23
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 9 Google 3 Unknown AI 3 Perplexity 1 ChatGPT 1 Ahrefs 1
crawler 18
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Encapsulate business rules as Specification objects with isSatisfiedBy($candidate) — combine with and()/or()/not() to build complex rules without giant if-statement blocks
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Complex eligibility or validation rules scattered across service methods not reusable or composable
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update

✓ schema.org compliant